1、安装
cnpm install better-scroll --sava
2、使用(在弹框内使用)
HTML
<!-- 祭拜弹框 -->
<van-popup
:lock-scroll="false"
class="popup_box"
v-model="showWorshipPopup"
position="bottom"
:style="{ height: '55%' }"
>
<div class="popup_title"><span>请选择祭拜品</span></div>
<div class="popup_content">
<div class="left" ref="left">
<ul class="content">
<li
v-for="(item, index) in left"
:key="item"
:class="{ current: currentIndex == index }"
@click="selectItem(index, $event)"
>
<span class="left-item">{{ item }}</span>
</li>
</ul>
</div>
<div class="right" ref="right">
<ul class="content">
<li
class="right-item right-item-hook"
v-for="(item, index) in right"
:key="index"
>
<h2>
<span>{{ item.name }}</span>
</h2>
<ul>
<li v-for="child in item.content" :key="child.id">
<div class="img_box">
<img :src="child.img" alt="" />
</div>
<div class="child_info">
<div class="info_left">
<h3>{{ child.name }}</h3>
<h4>价格:<span>{{ child.price?child.price/100+'元':'免费' }}</span></h4>
</div>
<div class="info_right" @click="gongfeng(child)">
<span>立即供奉</span>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</van-popup>
JS
import BScroll from "better-scroll";
export default {
data() {
return {
showWorshipPopup: false, //祭拜底部弹框
left: [],
right: [],
listHeight: [],
scrollY: 0, //实时获取当前y轴的高度
clickEvent: false,
lefts: null,
rights: null,
}
},
watch: {
showWorshipPopup(newValue, oldValue) {
if (newValue) {
this.$nextTick(() => {
this._initScroll();
this._getHeight();
});
}
},
},
computed: {
//
currentIndex() {
const index = this.listHeight.findIndex((item, index) => {
return (
this.scrollY >= this.listHeight[index] &&
this.scrollY < this.listHeight[index + 1]
);
});
return index > 0 ? index : 0;
},
},
methods: {
//初始化betterscroll
_initScroll() {
//better-scroll的实现原理是监听了touchStart,touchend事件,所以阻止了默认的事件(preventDefault)
//所以在这里做点击的话,需要在初始化的时候传递属性click,派发一个点击事件
//在pc网页浏览模式下,点击事件是不会阻止的,所以可能会出现2次事件,所以为了避免2次,可以在绑定事件的时候把$event传递过去
if (!this.lefts) {
this.lefts = new BScroll(this.$refs.left, {
click: true,
});
} else {
this.lefts.refresh();
}
if (!this.rights) {
this.rights = new BScroll(this.$refs.right, {
click: true,
probeType: 3, //探针的效果,实时获取滚动高度
});
} else {
this.rights.refresh();
}
//rights这个对象监听事件,实时获取位置pos.y
this.rights.on("scroll", (pos) => {
this.scrollY = Math.abs(Math.round(pos.y));
});
},
//获取滚动区域高度数组
_getHeight() {
let rightItems = this.$refs.right.getElementsByClassName(
"right-item-hook"
);
let height = 0;
this.listHeight.push(height);
for (let i = 0; i < rightItems.length; i++) {
let item = rightItems[i];
height += item.clientHeight;
this.listHeight.push(height);
}
console.log(this.listHeight, "98989");
},
//点击左侧分类
selectItem(index, event) {
this.clickEvent = true;
//在better-scroll的派发事件的event和普通浏览器的点击事件event有个属性区别_constructed
//浏览器原生点击事件没有_constructed所以当时浏览器监听到该属性的时候return掉
if (!event._constructed) {
return;
} else {
let rightItems = this.$refs.right.getElementsByClassName(
"right-item-hook"
);
let el = rightItems[index];
this.rights.scrollToElement(el, 300);
}
},
}
}
CSS
//祭拜弹框
.popup_box {
background: #f1f1f1;
display: flex;
flex-direction: column;
.popup_title {
width: 100%;
height: 0.44rem;
background: $defaultColor;
display: flex;
align-items: center;
color: #fff;
padding-left: 0.15rem;
font-size: 16px;
}
.popup_content {
flex: 1;
// margin-bottom: 0.12rem;
display: flex;
justify-content: space-between;
overflow: hidden;
.left {
flex: 0 0 1rem;
background-color: #fff;
margin-right: 0.1rem;
li {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 0.5rem;
position: relative;
}
.current {
background: #f1f1f1;
color: $defaultColor;
}
.current::after {
content: "";
width: 4px;
height: 15px;
border-radius: 5px 0 0 5px;
position: absolute;
background-color: $defaultColor;
top: 0;
right: 0px;
bottom: 0;
margin: auto;
}
}
.right {
flex: 1;
.right-item {
margin-top: 0.1rem;
background-color: #fff;
h2 {
display: flex;
align-items: center;
padding-left: 0.15rem;
height: 0.5rem;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
span {
margin-left: 0.05rem;
}
}
h2::before {
content: "";
width: 6px;
height: 6px;
border-radius: 50%;
background: $defaultColor;
}
li {
width: 100%;
padding: 0.15rem 0.1rem 0.15rem 0.15rem;
display: flex;
align-items: center;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
.img_box {
width: 0.6rem;
height: 0.6rem;
background: #efefef;
border-radius: 0.03rem;
padding: 0.1rem;
margin-right: 0.08rem;
img {
width: 100%;
height: 100%;
}
}
.child_info {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
.info_left {
h3 {
font-size: 14px;
line-height: 0.2rem;
margin-bottom: 0.05rem;
}
h4 {
display: flex;
align-items: center;
font-size: 12px;
color: $lightBlack;
span {
color: $defaultColor;
}
}
}
.info_right {
width: 0.72rem;
height: 0.3rem;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
background: $defaultColor;
border-radius: 0.06rem;
}
}
}
}
}
}
.popup_bottom {
width: 100%;
background: #ffff;
height: 0.44rem;
display: flex;
padding: 0 0.12rem;
align-items: center;
justify-content: space-between;
.bottom_left {
display: flex;
align-items: center;
span {
margin-right: 0.08rem;
}
/deep/ .van-switch {
width: 0.5rem;
height: 0.25rem;
border-radius: 0.25rem;
.van-switch__node {
width: 0.24rem;
height: 0.24rem;
}
}
/deep/ .van-switch--on .van-switch__node {
transform: translateX(0.25rem);
}
}
}
}