{{item.name}}
{{item.name}}
// script
// 数据是后台请求的,我这里就不贴出来了
data() {
address: {
province: '',
city: ''
}
},
computed: {
showAddress() {
let province = this.provinceList.find(item => item.id===this.address.province) || {name:'选择省'};
let city = this.cityList.find(item => item.id===this.address.city) || {name:'选择市'};
return `${province.name} - ${city.name}`;
}
}
对于我们的最终效果来说,是不是很简单呢?
当然,如果我这里写三个h-wrapper的话,我们自然而然就变成了三级联动
最外层的slector组件用来暴露在外部显示的文字,以及控制级联选择器的显示隐藏,在每一次开始一个新的功能的时候,我们应该先完成重点的功能,重点功能完成之后,再去修改一些样式包括交互效果
{{showValue || defaultShowValue}}
取消
{{title}}
确定
对于这个模板来说,需要解释的地方很少,我都写在注释里边
3. 接着,我们看一下最终的逻辑部分
首先需要重点提一下的是在mounted方法中,我们使用了this.$on方法,订阅了一个在当前组件内并没有发布的事件,这个事件,我定义在了h-wrapper这个组件中,稍后可以看到
其余的地方没有太复杂的功能和逻辑,就不一一解释
-
-
请选择
-
-
在模板中,需要重点关注的其实就是两个style,以及四个事件,当然了,还有插槽的位置,我这里使用了一个小技巧,在原始位置直接写好了四个option,并且其中一个还显示请选择,用来保证可选项的位置永远都可以处在最中间的位置
在逻辑中,我通过操作activeIndex这个索引值来动态的修改数据中ul的位移,使得当前永远显示的是对应索引与option高度计算出的位置
通过touchstart、touchmove、touchend三个事件来操作元素的位置与滑动
通过watch侦听对应属性,并实时触发事件,使得级联选择器发生改变,达到内外同步
通过mounted与updated钩子函数来保证当前的级联选择器属性会随着刷新而刷新
通过slot插槽来显示外部传入的option选项
对于option组件来说,并没有多少内容,它只需要负责显示数据,以及让级联选择器可以正确的获取到值即可
{{value}}
首先当前这个级联选择器的样式,我没有做太多的处理,但是已经很好看了有没有!
.h-selector {
letter-spacing: 1px;
font-size: 16px;
width: 100%;
height: 100%;
.h-selector-show {
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.h-selector-container {
position: absolute;
z-index: 999;
left: 0;
bottom: 0;
width: 100%;
background: #fff;
}
.h-selector-layer {
position: absolute;
background: rgba(0, 0, 0, 0.3);
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 2;
}
ul, li {
margin: 0;
padding: 0;
list-style: none;
}
.h-selector-header {
display: flex;
align-items: center;
height: 40px;
justify-content: space-between;
padding: 0 30px;
.h-selector-header-cancel {
color: #e9aa14;
}
.h-selector-header-confirm {
color: #508aff;
}
}
.h-selector-content {
display: flex;
width: 100%;
position: relative;
}
.h-selector-wrapper {
flex: 1;
overflow: hidden;
& + .h-selector-wrapper {
border-left: 1px solid #ddd;
}
}
.h-selector-option {
line-height: 60px;
height: 60px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.h-selector-bg {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
background: linear-gradient(180deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.7)), linear-gradient(0deg, hsla(0, 0%, 100%, 0.9), hsla(0, 0%, 100%, 0.4));
backface-visibility: hidden;
pointer-events: none;
background-repeat: no-repeat;
background-position: top, bottom;
background-size: 100% 100px;
}
.h-selector-move-enter-to, .h-selector-move-leave {
transform: translate3d(0, 0, 0);
}
.h-selector-move-enter-active, .h-selector-move-leave-active {
transition: transform .6s;
}
.h-selector-move-enter, .h-selector-move-leave-to {
transform: translate3d(0, 100%, 0);
}
.h-selector-fade-enter-to, .h-selector-fade-leave {
opacity: 1;
}
.h-selector-fade-enter-active, .h-selector-fade-leave-active {
transition: opacity .4s;
}
.h-selector-fade-enter, .h-selector-fade-leave-to {
opacity: 0;
}
}
最终,我们就已经成功的打造了一款移动端的级联选择器,可以实现一级二级三级联动,当然了,多级也没有任何问题,但是在移动端,我建议最多到三级联动,否则的话影响用户体验感