uni-app | 封装一个二级国内城市选择器(citypicker)
在实际uniapp,微信小程序,h5的项目中,经常用到picker
官方的定义:从底部弹起的滚动选择器。支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器,日期选择器,省市区选择器,默认是普通选择器。
一共有5种模式,有满足用户需求的省市区选择器。
再看看该模式的文档
我们可以看到兼容性来说,还是不太好。而且只能是三级,与实际需求不太符合,那这样我们就来自己基于原生的picker封装一个二级citypicker
先上界面代码:
<template>
<view class="uni-city-picker">
<picker @change="cityChange" @columnchange="columnChange" mode="multiSelector" :value="cityIndex" :range="citys">
<!-- 预留的插槽 -->
<slot></slot>
</picker>
</view>
</template>
然后是js部分:
data() {
return {
citys: [
[],
[]
],
cityIndex: [ ], // 默认
cityArr: [
{
text: "天津",
City: [{
text: "天津"
}, ]
},
{
text: "河北",
City: [{
text: "石家庄"
},
{
text: "唐山"
},
{
text: "秦皇岛"
},
{
text: "邯郸"
},
{
text: "邢台"
},
{
text: "保定"
},
{
text: "张家口"
},
{
text: "承德"
},
{
text: "沧州"
},
{
text: "廊坊"
},
{
text: "衡水"
}
]
}
// 这里省略了地区的json数据,在网络上可以随便找到
],
}
},
mounted() {
this.citys[0] = this.cityArr.map((item) => { // 一级省份
return item.text
})
this.citys[1] = this.cityArr.filter((item) => { // 二级市区
return item.text === "天津"
})[0].City.map((child) => {
return child.text
})
this.cityIndex = [0, 0]
},
methods: {
cityChange(e) { // 值改变了
const index1 = e.detail.value[0] ? e.detail.value[0] : 0
const index2 = e.detail.value[1] ? e.detail.value[1] : 0
console.log(e.detail)
const city = [ this.cityArr[index1].text , this.cityArr[index1].City[index2].text]
this.$emit('cityChange', city)
},
columnChange(e) { //列值改变(拖动第一列)
// console.log(e.detail)
const index = e.detail.value
if (e.detail.column === 0) {
let cityChild = []
this.cityArr[index].City.forEach((child) => {
cityChild.push(child.text)
})
this.citys[1] = cityChild
this.cityIndex.splice(1, 1, 0)
this.cityIndex[0] = index
}
}
}
}
在页面中的使用方式
<citypicker @cityChange="cityChange">
<template>
<view>这里是插槽内容</view>
</template>
</citypicker>
这里@cityChange会返回一个数组结构,第一个值为第一列的地区名字,第二个值是二级地区的名字