前两天在公司用vue开发移动端的项目,遇到一个功能,要求弹出一个选择器,默认选中中间的值,要求选中的值跟着滚动改变,由于没有外网,只能自己开发一个来实现这个需求。第一次写博客,写的不好,勿喷~
<template>
<div class="picker-main">
<button @click="showPicker()">选择器</button>
<span>{{city}}</span>
<div
v-if="show"
class="picker"
>
<section class="picker-main">
<h3>
<span @click="show = false">取消</span>
<span>请选择</span>
<span @click="sure()">确认</span>
</h3>
<ul ref="ul">
<li
v-for="(item, index) in list"
:key="index"
:class="active==item.id?'active':active==item.id-1||active==item.id+1?'active2':null"
:ref="'li'+item.label"
>{{item.val}}</li>
</ul>
</section>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [
{ id: -9, city: "", label: "a" },
{ id: -9, city: "", label: "b" },
{
id: 0,
val: "北京",
label: "bj"
},
{
id: 1,
val: "上海",
label: "sh"
},
{
id: 2,
val: "广州",
label: "gz"
},
{
id: 3,
val: "深圳",
label: "sz"
},
{
id: 4,
val: "北海",
label: "bh"
},
{ id: -9, city: "", label: "c" },
{ id: -9, city: "", label: "d" }
],
show: false,
active: 0,
city: "",
listOffsetTop: [],
timer: null
};
},
methods: {
showPicker() {
this.show = true;
this.active = 0;
this.timer = setTimeout(() => {
clearTimeout(this.timer);
this.getOffsetTop();
this.computeActive();
}, 50);
},
sure() {
this.list.map((item, index) => {
item.id == this.active ? (this.city = item.val) : null;
});
this.show = false;
},
getOffsetTop() {
this.listOffsetTop = [];
this.list.map((item, index) => {
let liTop = this.$refs["li" + item.label];
this.listOffsetTop.push(liTop[0].offsetTop - 41);
});
},
computeActive() {
let scroll = this.$refs.ul;
scroll.addEventListener("scroll", () => {
this.listOffsetTop.map((item, index) => {
item <= scroll.scrollTop + 100 ? (this.active = index - 2) : null;
});
});
}
}
};
</script>
<style lang="less" scoped>
.picker {
background-color: rgba(0, 0, 0, 0.2);
max-height: 100vh;
width: 100%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: flex;
.picker-main {
width: 100%;
position: absolute;
bottom: 0;
background-color: #fff;
h3 {
padding: 0;
margin: 0;
display: flex;
justify-content: space-around;
border-bottom: solid 1px #ddd;
font-size: 20px;
line-height: 40px;
}
ul {
max-height: 250px;
padding: 0;
margin: 0;
overflow: auto;
background-color: #fff;
li {
list-style: none;
font-size: 25px;
line-height: 50px;
text-align: center;
opacity: 0.3;
height: 50px;
background-color: #fff;
}
}
}
}
.active {
background-color: #ddd !important;
color: #333;
opacity: 1 !important;
}
.active2 {
color: #333;
opacity: 0.6 !important;
}
</style>
1.我们在弹出方法的时候设置一个settimeout()方法,目的是为了数据能够挂载到页面上去之后在执行下面的方法,如果没有这个方法,就获取不到指定的ref的值。
2.循环遍历list数组,用数组listOffsetTop来存储每一条数据渲染后的offsetTop。
3.给列表的父容器ul添加一个scroll监听,当父容器的scrollTop发生变化时能够监听到变化。
4.遍历listOffsetTop数组,用父容器的scrollTop和数组listOffsetTop内的值进行比较,通过判断的值进行改变选中的目标值
至此,滚动选择器功能就已经实现了,希望这篇文章对大家有所帮助(第一次写博客,望大家包含,谢谢!)
有疑问的可以和我一起探讨改进!
QQ:981661072