一、需求背景
在电商系统中地区选择是比较常见、公用的一个功能,地区数据,多级联动(省、市、区、镇):
本文分享了Javashop电商系统的小程序端地区选择组件的实现。
二、代码封装
首先在components文件下新建一个regionpicke文件夹, 再在该文件夹下新建Component(一个自定义组件由json,wxml,wxss,js四个文件组成)
json文件中设置component字段为true (声明该文件为自定义组件)
{
"component": true
}
组件内的wxml:
<view class='area-nav'>
<view class='choosed-area'>
<view wx:for="{{choosedAreas}}" wx:key="index" wx:if="{{choosedAreas.length}}" class="nav-li {{item && item.region_grade === areas[0].region_grade ? 'selected':''}}" bindtap="onchangeChoosedItem" data-item="{{item}}">{{item.local_name || '请选择'}}</view>
<view wx:if="{{!choosedAreas.length || !finished}}">请选择</view>
</view>
</view>
<view class='main'>
<scroll-view scroll-y="true" class='main-ul'>
<view class="main-li {{item.selected ? 'selected':''}}" wx:for="{{areas}}" wx:key="index" bindtap='onchangeItem' data-item="{{item}}">
<text class='item'>{{item.local_name}}</text>
<text wx:if="{{item.selected}}" class='iconfont icon-duigou icon'></text>
</view>
</scroll-view>
</view>
组件内的js:
/**
* 地区选择组件
* ===== 使用场景 ======
* 所有选择地区的地方
* ===== 参数 =====
* show 地区组件是否显示
* ===== 事件 =====
* areasChanged 选择地区时触发,把选择的新地区传给父组件
* closeRegionpicke 监听地区是否选择完毕,选择完毕后关闭地区组件
* 触发areasChanged事件,即在外部,在组件上绑定areasChanged事件即可, 即bind:areasChanged,像绑定tap一样
*/
import * as API_Address from '../../api/address'
Component({
//接收父组件传递过来的参数
properties:{
show: {
type: Boolean,
value: false
}
},
data:{
id: 0,
areas: [],//当前级别显示的地区
selectedAreas: [],//存储当前选中项所属的地区列表
choosedAreas: [],//选中的地区
finished: false,//是否选择完毕
},
observers:{
//监听地区组件是否显示
show(val) {
if(val) {
this.getAreasItems()
}
},
//监听地区是否选择完毕,选择完毕后通知父组件关闭地区组件
finished() {
if (this.data.finished) {
this.triggerEvent('closeRegionpicke')
}
},
//把选择的新地区传给父组件
choosedAreas(newVal) {
this.triggerEvent('areasChanged', newVal)
}
},
methods:{
// 已选择的地区变化时触发
onchangeChoosedItem(e) {
let item = e.currentTarget.dataset.item
if (item.region_grade) {
this.setData({
areas: this.data.selectedAreas[item.region_grade - 1]
})
}
},
// 选择列表地区项变化时
onchangeItem(e) {
let item = e.currentTarget.dataset.item
if (this.data.choosedAreas[item.region_grade - 1] && this.data.areas[0].region_grade === item.region_grade && item.id === this.data.choosedAreas[item.region_grade - 1].id) {
return
} else {
this.data.choosedAreas.length = item.region_grade - 1
if (this.data.choosedAreas[item.region_grade - 1]) {
this.data.choosedAreas[item.region_grade - 1] = item
} else {
this.data.choosedAreas.push(item)
}
//设置选择后的地区为选中状态
this.data.areas.forEach(key => {
if (item.id === key.id) {
key.selected = true
}else{
key.selected = false
}
})
item.selected = true
this.setData({
finished: item.region_grade === 4,
id: item.id,
areas:this.data.areas,
choosedAreas: this.data.choosedAreas,
})
if (item.region_grade === 4) {
return
}
this.getAreasItems()
}
},
//获取地区列表
getAreasItems() {
let that = this
//调用后台接口获取地区列表
API_Address.getAreas(this.data.id).then(response => {
if (response && Array.isArray(response) && response.length) {
response.forEach(key => {
key.selected = false
})
that.setData({areas: response})
if (that.data.selectedAreas[response[0].region_grade - 1]) {
if (response[0].region_grade === that.data.selectedAreas[response[0].region_grade - 1][0].region_grade) {
that.data.selectedAreas[response[0].region_grade - 1] = response
}
} else {
that.data.selectedAreas.push(response)
that.setData({selectedAreas:this.data.selectedAreas})
}
} else {
that.setData({finished: true})
}
})
}
}
})
三、组件调用
在需要的文件中引入组件
json文件
说明:"组件名称(随便定义)":"组件页面的路径
{
"usingComponents": {
"RegionPicker": "/components/regionpicke/regionpicke"
}
}
wxml文件
<RegionPicker
bind:areaschanged="addressSelectorChanged"
bind:cloneRegionPicke="cloneRegionPicke"
show="{{ showAddressSelector }}"
></RegionPicker>
js文件
//地址发生改变
addressSelectorChanged(e){
const item = e.detail //接收组件传递过来的参数
const obj = {
last_id: item[item.length - 1].id,
addrs: item.map(key => { return key.local_name }).join(' ')
}
this.setData({
'addressForm.region': obj.last_id,
'addressForm.addrs': obj.addrs
})
},
//关闭地区组件
cloneRegionPicke() {
this.setData({
showAddressSelector: false
})
}
易族智汇(javashop)原创文章