组件实现功能:从底部弹出地区选择器,最多支持三级选择且可以自由选择级联数,加入了动画效果
最终效果如图:
组件已上传到插件市场,插件ID:cc-address-selector,引入可直接使用
下面是代码参考
HTML:
<template>
<view class="address-selector">
<!-- 遮罩层 -->
<view class="mask" v-if="show" @click="show = false" @touchmove.prevent.stop=""></view>
<!-- 地区选择器 -->
<view class="address-selector__main" :class="show ? 'address-selector__main--show' : ''">
<view class="address-selector__title">
<!-- 标题 -->
<view class="f-c mb address-selector__title-text">选择地区</view>
<!-- 顶部文字 -->
<view class="f-s">
<view class="address-selector__item">
<text class="address-selector__sub" @click="selectType(1)" :class="active === 1 ? 'address-selector__sub--active' : ''">{{ activeTitle.title1 }}</text>
</view>
<view class="address-selector__item" style="text-align: center;">
<text class="address-selector__sub" @click="selectType(2)" v-show="active > 1" :class="active === 2 ? 'address-selector__sub--active' : ''">
{{ activeTitle.title2 }}
</text>
</view>
<view class="address-selector__item" style="text-align: right;">
<text class="address-selector__sub" @click="selectType(3)" v-show="active > 2" :class="active === 3 ? 'address-selector__sub--active' : ''">
{{ activeTitle.title3 }}
</text>
</view>
</view>
</view>
<!-- 一级数据 -->
<view class="address-selector__trans" v-show="active === 1">
<view
class="address-selector__text"
v-for="(v, index) in districtData1"
:key="index"
@click.stop="selectList(index, v, 0)"
:class="index == selectData[0] ? 'address-selector__text--active' : ''"
>
{{ v[title] }}
</view>
</view>
<!-- 二级数据 -->
<view class="address-selector__trans" v-show="active === 2">
<view
class="address-selector__text"
v-for="(x, i) in districtData2"
:key="i"
@click.stop="selectList(i, x, 1)"
:class="i == selectData[1] ? 'address-selector__text--active' : ''"
>
{{ x[title] }}
</view>
</view>
<!-- 三级数据 -->
<view class="address-selector__trans z" v-show="active === 3">
<view
class="address-selector__text"
v-for="(val, n) in districtData3"
:key="n"
@click.stop="selectList(n, val, 2)"
:class="n == selectData[2] ? 'address-selector__text--active' : ''"
>
{{ val[title] }}
</view>
</view>
</view>
</view>
</template>
JS部分
<script>
export default {
name: 'addressSelector',
data() {
return {
// 是否展示
show: false,
// 当前级别
active: 1,
// 标题显示
activeTitle: {
title1: '请选择',
title2: '请选择',
title3: '请选择'
},
// 二级数据
districtData2: [],
// 三级数据
districtData3: [],
// 选中的下标
selectData: []
};
},
props: {
// 所有数据/一级数据
districtData1: {
type: Array,
default: () => []
},
// 级联数
level: {
type: Number,
default: () => 3
},
// 显示的文字的参数名
title: {
type: String,
default: () => 'title'
}
},
created() {},
methods: {
showSelector(selectData = []) {
// 打开选择器时传入selectData代表默认选中的位置
if (selectData.length > 0) {
this.selectData = selectData;
this.active = selectData.length;
selectData.forEach((item, index) => {
if (index > 0) {
this[`districtData${index + 1}`] = this[`districtData${index}`][item].children;
}
this.activeTitle[`title${index + 1}`] = this[`districtData${index + 1}`][item][this.title];
});
}
// 弹出选择器
this.show = true;
},
// 点击标题事件
selectType(v) {
this.active = v;
if (v === 1) {
this.selectData = [this.selectData[0]];
this.activeTitle.title2 = '请选择';
this.activeTitle.title3 = '请选择';
} else if (v === 2) {
this.selectData = [this.selectData[0], this.selectData[1]];
this.activeTitle.title3 = '请选择';
}
},
// 选择列表事件
selectList(v, data, n) {
let that = this;
const level = n + 1;
this.selectData[n] = v;
this.activeTitle[`title${level}`] = data[this.title];
if (level === this.level) {
this.show = false;
// 传递参数,分别为选择的文字对象,最后选择的子节点的数据,以及选择数据的下标(可以根据下标来获取父节点)
this.$emit('getAddress', that.activeTitle, data, this.selectData);
} else if (level < this.level) {
this[`districtData${level + 1}`] = this[`districtData${level}`][v].children;
this.active += 1;
}
}
}
};
</script>
CSS部分
<style lang="scss" scope>
// 遮罩层
.mask {
background: rgba(0, 0, 0, 0.4);
position: fixed;
z-index: 100;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
}
.address-selector__item {
flex: 1;
}
.address-selector__main {
width: 100%;
height: 888rpx;
background: #fff;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
overflow: hidden;
position: fixed;
z-index: 101;
bottom: 0;
left: 0;
transform: translateY(100%);
transition: transform 0.5s;
}
.address-selector__main--show {
transform: translateY(0);
}
.address-selector__title {
padding: 20rpx 44rpx 0 44rpx;
border-bottom: 1px solid #f1f1f1;
font-size: 28rpx;
color: #333;
height: 124rpx;
&-text {
font-size: 28rpx;
font-weight: bold;
color: #333333;
}
.f-s {
height: 40rpx;
}
}
.address-selector__sub {
height: 44rpx;
flex: 1;
}
.address-selector__sub--active {
border-bottom: 4rpx solid #ee1616;
}
.address-selector__trans {
padding: 20rpx 44rpx;
padding-bottom: 0;
overflow-y: scroll;
height: 764rpx;
width: 100%;
position: fixed;
right: 0;
padding-bottom: $safe;
bottom: 0;
z-index: 102;
background: #fff;
}
.address-selector__text {
font-size: 28rpx;
color: #333;
padding: 20rpx 0;
}
.address-selector__text--active {
color: #ee1616;
}
</style>
使用方法
在页面中使用组件,自定义一个ref名称进行方法的调用,目前最多只支持一二三级,需要做更多的可以自己修改
传参说明
示例
<template>
<cc-address-selector ref="addressSelector" :districtData1="regionData" :level="2" :title="name" @getAddress="getAddress"></cc-address-selector>
</template>
methods: {
// 获取地区数据
getAddress(title, data) {
// 这里写自己的赋值操作
},
// 打开地区选择器
showSelector() {
this.$refs.addressSelector.showSelector();
}
}