之前在mpvue
小程序的项目中有遇到手动封装一个省市区选择器组件的需求,但当时因为时间比较紧,做得不是很好,一直挺遗憾。最近抽了一些时间终于重新把这个组件重新封装了一遍。这篇博客主要介绍一下怎么用、默认选中功能和一些实现的原理。
先展示一下做好的效果:

项目地址
如何使用
-
这个选择器组件就是一个.vue文件,所有的样式和逻辑都在里面。所以只需要在需要使用它的父组件中引入
src/components/regionSelector.vue
文件。 -
那么选择器中全国这么多省市区的信息来自于哪里呢?
所以我们还需要在regionSelector.vue
中引入mapInfo
目录下的mapInfo.js
文件,它保存并输出了全国所有省市区的信息。
我已经在regionSelector.vue
中引入了它。如果需要变更它们的相对路径,可以自行修改。
//regionSelector.vue
import mapInfo from "../../mapInfo/mapInfo";
- 现在需要准备的文件都已经OK。接下来是如何控制选择器的弹出和移出。
引入选择器后,先为它传入一个名叫isShow
的Boolean类型的prop,建议与某一个Boolean类型的数据属性绑定,初始值设为false。方便控制。
如果想让选择器弹出,将绑定的数据属性的值设为true
即可。
如果想让选择器移出,比如点击了确定按钮、取消按钮、蒙层时,选择器组件会触发hideSelector
事件,我们在父组件中监听它,并在它的事件处理函数中将绑定的数据属性的值设为false
即可。
示例代码:
<template>
<div>
<button @click="showSelector">选择省市区</button>
<region-selector :isShow="selectorShow" @hideSelector="hideSelector"></region-selector>
</div>
</template>
<script>
import regionSelector from '@/components/regionSelector';
export default {
components: { regionSelector },
data() {
return { selectorShow: false }
},
methods: {
showSelector() { //点击button时,控制选择器弹出
this.selectorShow = true;
},
hideSelector(info) { //触发hideSelector事件时,控制选择器移出
console.log(info);
this.selectorShow = false;
}
}
}
</script>
- 另外,你可能会发现
hideSelector
的事件处理函数中有一个参数info
。当你点击了确定按钮时,不光选择器会被移出,info
也会被传入,它是一个对象数组,有三个对象,依次表示点击确定按钮时被选中的省、市、区的信息。
比如开头的动图中我选中了河南省 / 开封市 / 禹王台区,那么info
的值为:
[
{ id: '410000', name: '河南省', index: 15 },
{ id: '410200', name: '开封市', index: 1 },
{ id: '410205', name: '禹王台区', index: 3 }
]
//index是指当前选中项是它所在列的第几项,比如河南省index为15,即它在省一列的第16项
当然如果你点击的是其他地方,info
的值为null
。
附加功能:默认选中
在使用省市区选择器时,为了让用户的使用体验更好,常常需要在用户打开选择器时,就默认为用户选中现有地址的省、市、区。比如开头的动图中,默认选中 山东省 / 济南市 / 历下区。
组件实现了打开时默认选中省市区的功能,使用也很简单。只需要将想要默认选中的省、市、区的名字传入province
、city
、district
这个三个prop即可。
示例代码:
<region-selector
:isShow="selectorShow"
province="山东省" city="济南市" district="历下区"
@hideSelector="hideSelector"></region-selector>
<!--直接传入字符串或绑定到数据属性都可以-->
部分实现原理
- 封装选择器使用的微信原生组件
封装组件使用微信原生组件是<picker-view>
和<picker-view-column>
。
微信原生的还有一个<picker mode="selector">
单列选择器组件,用它来封装省市区选择器可能会更方便一些,很多工作微信已经做好了,但个人感觉用它虽然方便,但可操作的空间太小了,失去了很多快乐。 - 省市区信息的存储
所有的行政区信息在第一次使用组件的时候,就被存储到缓存中。在beforeCreated
生命周期中触发。
beforeCreate() {
if (!wx.getStorageSync('mapInfo')) {
wx.setStorageSync("mapInfo", mapInfo);
}
}
- 弹出和移出选择器
之所以之前要将isShow
这个prop与一个Boolean类型的数据属性绑定,实际上是因为选择器内部用watch
监听了isShow
。当isShow
的值变为true
,就会调用让选择器从底部弹出的方法;当isShow
的值变为false
,就会调用让选择器移出的方法。
watch: {
isShow(val) {
if (val) {
this.showSelector();
} else {
this.hideSelector();
}
}
}
- 样式自定义
由于使用的<picker-view>
和<picker-view-column>
组件可操作性很高,所以选择器的很多样式都可以自定义,比如确定、取消按钮的颜色、选择器的背景、蒙层的透明度等等,都可以更改。直接在regionSelector.vue
中的样式部分修改即可。
如果感到这篇博客对你有帮助,麻烦点个赞~