vue+mint-ui 组件实现省市县三级联动功能
是Vue和mint-ui结合实现的省市区三级联动效果
·
工作中经常会遇到需要前端实现省、市、区(县)的三级选择的场景,今天要介绍的是Vue和mint-ui结合实现的三级联动效果。
三级联动
我认为实现的难点在于mint-ui,Picker组件展示省市区三级联动数据上,建议先熟悉下mintUI的组件。
官方的解释:
个人理解:
- defaultIndex -> 默认展示数据的下标,默认序号为0
- values -> 该数据选项的数据
- className -> 数据展示的位置(数据本身的显示顺序)
- textAlign -> 对齐方式
- flex -> 将整个picker分成几份,他自己所占位置
附上官方文档地址picker组件
[{
flex: 1,
defaultIndex: this.provinceIndex, //对应 slot 初始选中值
values: Object.values(this.myaddress)[0],//对应 slot 的备选值数组
className: 'slot1', //对应 slot 的类名
textAlign: 'center' //数据对齐格式
},
{
flex: 1,
defaultIndex: this.cictyIndex,
values: (Object.values(this.myaddress)[0])[this.provinceIndex].c,
className: 'slot2',
textAlign: 'center'
},
{
flex: 1,
defaultIndex: this.regionIndex,
values: ((Object.values(this.myaddress)[0])[this.provinceIndex].c)[this.cictyIndex].a,
className: 'slot3',
textAlign: 'center'
}]
话不多说,直接上代码
1、准备省市区三级联动的数据
附上一部分省市区的json代码,有需要的可以和我联系
{
"citylist": [{
"p": "北京市",
"c": [{
"n": "市辖区",
"a": [{
"s": "东城区"
}, {
"s": "西城区"
}, {
"s": "朝阳区"
}, {
"s": "丰台区"
}, {
"s": "石景山区"
}, {
"s": "海淀区"
}, {
"s": "门头沟区"
}, {
"s": "房山区"
}, {
"s": "通州区"
}, {
"s": "顺义区"
}, {
"s": "昌平区"
}, {
"s": "大兴区"
}, {
"s": "怀柔区"
}, {
"s": "平谷区"
}, {
"s": "密云区"
}, {
"s": "延庆区"
}]
}]
}, {
"p": "天津市",
"c": [{
"n": "市辖区",
"a": [{
"s": "和平区"
}, {
"s": "河东区"
}, {
"s": "河西区"
}, {
"s": "南开区"
}, {
"s": "河北区"
}, {
"s": "红桥区"
}, {
"s": "东丽区"
}, {
"s": "西青区"
}, {
"s": "津南区"
}, {
"s": "北辰区"
}, {
"s": "武清区"
}, {
"s": "宝坻区"
}, {
"s": "滨海新区"
}, {
"s": "宁河区"
}, {
"s": "静海区"
}, {
"s": "蓟州区"
}]
}]
}]
}
2、在index.vue中引入省市区三级联动的子组件
//引入子组件
import selectArea from '@/areaselect/index.vue'
<select-area filed-label-text="幼儿园所在地区" :cictyArea.sync="userFormData.base.cictyArea"></select-area>
export default {
components: {
selectArea
},
data() {
return {
userFormData: {
base: {
cictyArea: '',
detailAddress: '',
insuredAdress: '',
}
}
}
}
}
3、实现省、市、区 三级联动的子组件
//省市区三级联动
<template>
<div class="area-select">
<div @click="getInsuredArea">
<mt-field :label="filedText" :placeholder="'请选择' + filedText" v-model="basearea" disabled>
<span>
<img width="20px" :src="areaIcon" />
</span>
</mt-field>
</div>
<!-- 地区 -->
<mt-popup v-model="insuredAreaVisiable" position="bottom" style="width:100%">
<mt-picker :slots="insuredArea" value-key="p" @change="onAddressChange" ref="pickerArea" show-toolbar>
<div class="picker-toolbar-box">
<span class="picker-toolbar-ok" @click="confirmArea">确认</span>
</div>
</mt-picker>
</mt-popup>
</div>
</template>
划重点来了
import myAddress from './tabs/cicty.json'
export default {
data() {
return {
filedText: this.filedLabelText || '投保地区', //页面显示label
insuredArea: [], //弹框显示数据
basearea: this.cictyArea, //页面显示 省市区 例 河北省/石家庄市/市辖区
chooseObj: { //选中的省市区
province: '',
cicty: '',
region: ''
},
province: '', //省
cicty: '', //市
region: '', //区
defaultIndex: false,
provinceIndex: 0, //所选省下标
cictyIndex: 0, //所选市下标
regionIndex: 0, //所选区下标
insuredAreaVisiable: false, //弹框显隐控制
areaIcon: require('@/assets/svg/location.svg'),
handler: function(e) {e.preventDefault()} //阻止默认操作
}
},
props: {
cictyArea: {
type: String,
default: ''
},
filedLabelText: {
type: String,
default: ''
}
},
mounted() {
let address = JSON.stringify(myAddress).replace(/n/g, 'p')
address = address.replace(/s/g, 'p')
address = address.replace(/市辖区/, '市辖区')
this.myaddress = JSON.parse(address)
this.insuredArea = [{
flex: 1,
defaultIndex: this.provinceIndex,
values: Object.values(this.myaddress)[0],
className: 'slot1',
textAlign: 'center'
},
{
flex: 1,
defaultIndex: this.cictyIndex,
values: (Object.values(this.myaddress)[0])[this.provinceIndex].c,
className: 'slot2',
textAlign: 'center'
},
{
flex: 1,
defaultIndex: this.regionIndex,
values: ((Object.values(this.myaddress)[0])[this.provinceIndex].c)[this.cictyIndex].a,
className: 'slot3',
textAlign: 'center'
}
]
},
methods: {
// 弹层出现
closeTouch() {
document.getElementsByTagName("body")[0].addEventListener('touchmove', this.handler,{passive:false});
},
// 弹层关闭
openTouch() {
document.getElementsByTagName("body")[0].removeEventListener('touchmove',this.handler,{passive:false});
},
onAddressChange(picker, values) {
if (values[0]) {
picker.setSlotValues(1, values[0].c)
picker.setSlotValues(2, values[1].a)
}
if (values && values.length > 0) {
this.province = values[0].p
this.cicty = values[1].p
this.region = values[2].p
}
},
remeberIndex(province, cicty, region) {
for (let i = 0; i < (Object.values(this.myaddress)[0]).length; i++) {
if (province === (Object.values(this.myaddress)[0])[i].p) {
this.provinceIndex = i
}
}
for (let i = 0; i < ((Object.values(this.myaddress)[0])[this.provinceIndex].c).length; i++) {
if (cicty === ((Object.values(this.myaddress)[0])[this.provinceIndex].c)[i].p) {
this.cictyIndex = i
}
}
for (let i = 0; i < (((Object.values(this.myaddress)[0])[this.provinceIndex].c)[this.cictyIndex].a)
.length; i++) {
if (region === (((Object.values(this.myaddress)[0])[this.provinceIndex].c)[this.cictyIndex].a)[i].p) {
this.regionIndex = i
}
}
},
getInsuredArea() {
this.closeTouch()
this.insuredAreaVisiable = true
this.defaultIndex = false
},
// 地区
confirmArea() {
if(!this.province) {
this.province = (Object.values(this.myaddress)[0])[0].p
this.cicty = ((Object.values(this.myaddress)[0])[this.provinceIndex].c)[0].p
this.region = (((Object.values(this.myaddress)[0])[this.provinceIndex].c)[this.cictyIndex].a)[0].p
}
this.chooseObj.province = this.province
this.chooseObj.cicty = this.cicty
this.chooseObj.region = this.region
this.basearea = this.chooseObj.province + '/' + this.chooseObj.cicty.trim() + '/' + this.chooseObj.region
this.insuredAreaVisiable = false
this.openTouch()
this.defaultIndex = true
this.$emit('update:cictyArea', this.basearea)
}
}
}
完整代码上传到资源了,有需要的自行下载
更多推荐
已为社区贡献9条内容
所有评论(0)