一、需求背景
在电商系统中地区选择是比较常见、公用的一个功能,地区数据,多级联动(省、市、区、镇):
本文分享了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)原创文章