小程序自定义组件之省市区地址三级联动
wxml结构图如下
1 <!--components/ares/area.wxml--> 2 <!-- 自定义地图插件用于使用第三方地图数据包 by张涛20180307 --> 3 <view class="area-box" wx:if="{{isShow}}" data-address="{{address}}"> 4 <view class="area-btn"> 5 <view class="area-btn-off" catchtap='_cancelEvent' >取消</view> 6 <view class="area-btn-on" catchtap='_confirmEvent'>确认</view> 7 </view> 8 <picker-view indicator-style="height:50px;" style="width:750rpx; height:200px;" value="{{value}}" bindchange="bindChange"> 9 <picker-view-column> 10 <view wx:for="{{area.province}}" wx:key='' style="line-height: 50px;text-align:center;">{{item.name}}</view> 11 </picker-view-column> 12 <picker-view-column> 13 <view wx:for="{{area.city}}" wx:key='' style="line-height: 50px;text-align:center">{{item.name}}</view> 14 </picker-view-column> 15 <picker-view-column> 16 <view wx:for="{{area.area}}" wx:key='' style="line-height: 50px;text-align:center">{{item.name}}</view> 17 </picker-view-column> 18 </picker-view> 19 </view>
json包如下
1 { 2 "component":true, 3 "usingComponents":{} 4 }
wxss样式图如下
1 /*自定义地图插件用于使用第三方地图数据包 by张涛20180307*/ 2 .area-box{position:fixed;bottom:0;left:0;background:white;box-shadow:0 0 10px 10px #f2f2f2;} 3 .area-btn{width:100%;height:80rpx;font-size:28rpx;display:flex;justify-content:space-between;align-items:center;border-bottom:2rpx solid #ff9f09;} 4 .area-btn .area-btn-off{width:140rpx;line-height:80rpx;text-align:center;} 5 .area-btn .area-btn-on{width:140rpx;line-height:80rpx;color:#ff9f09;text-align:center;}
js代码如下
1 // 自定义地图插件用于使用第三方地图数据包 by张涛20180307 2 // components/Dialog/dialog.js 3 const util = require('../../utils/request.js'); 4 Component({ 5 options: { 6 multipleSlots: true // 在组件定义时的选项中启用多slot支持 7 }, 8 /** 9 * 组件的属性列表 10 * 用于组件自定义设置 11 */ 12 properties: { 13 // 模拟数据 14 provinces: { // 属性名 15 type: Array, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) 16 value:[{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000}] // 属性初始值(可选),如果未指定则会根据类型选择一个 17 }, 18 citys: { // 属性名 19 type: Array, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) 20 value:[{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000}] // 属性初始值(可选),如果未指定则会根据类型选择一个 21 }, 22 areas: { // 属性名 23 type: Array, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型) 24 value:[{'name':"丰台区",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000},{'name':"北京",'code':1000000}] // 属性初始值(可选),如果未指定则会根据类型选择一个 25 } 26 }, 27 28 /** 29 * 私有数据,组件的初始数据 30 * 可用于模版渲染 31 */ 32 data: { 33 // 弹窗显示控制 34 isShow:false, 35 value:'', 36 area:{ 37 province:[], 38 city:[], 39 area:[] 40 }, 41 provinceCode:'', 42 cityCode:'', 43 areaCode:'', 44 address:{ 45 province:'', 46 city:'', 47 area:'' 48 }, 49 // 滚动地址后的最后位置点 50 areaList:[] 51 }, 52 /* 53 *组件生命周期函数,在组件实例进入页面节点树时执行 54 */ 55 attached:function(){ 56 this.getProvince(); 57 }, 58 /** 59 * 组件的方法列表 60 * 更新属性和数据的方法与更新页面数据的方法类似 61 */ 62 methods: { 63 /* 64 * 公有方法 65 */ 66 // 地址三级请求函数 67 // 省 68 getProvince(){ 69 var _this=this; 70 util.POST('/mobile/common/getArea','',{'parentCode':this.data.provinceCode},function(res){ 71 _this.data.area.province=res.data.result; 72 _this.setData({ 73 area:_this.data.area, 74 provinceCode:res.data.result[0].code 75 }) 76 _this.getCity(); 77 }) 78 }, 79 // 市 80 getCity(){ 81 var _this=this; 82 util.POST('/mobile/common/getArea','',{'parentCode':this.data.provinceCode},function(res){ 83 _this.data.area.city=res.data.result; 84 _this.setData({ 85 area:_this.data.area, 86 cityCode:res.data.result[0].code 87 }) 88 _this.getArea(); 89 }) 90 }, 91 // 区 92 getArea(){ 93 var _this=this; 94 util.POST('/mobile/common/getArea','',{'parentCode':this.data.cityCode},function(res){ 95 _this.data.area.area=res.data.result; 96 _this.setData({ 97 area:_this.data.area, 98 areaCode:res.data.result[0].code, 99 address:{ 100 province:_this.data.area.province[_this.data.areaList[0]?_this.data.areaList[0]:0], 101 city:_this.data.area.city[_this.data.areaList[1]?_this.data.areaList[1]:0], 102 area:_this.data.area.area[_this.data.areaList[2]?_this.data.areaList[2]:0] 103 } 104 }) 105 }) 106 }, 107 //隐藏弹框 108 hideDialog(){ 109 this.setData({ 110 isShow: !this.data.isShow 111 }) 112 }, 113 //展示弹框 114 showDialog(){ 115 this.setData({ 116 isShow: !this.data.isShow 117 }) 118 }, 119 /* 120 * 内部私有方法建议以下划线开头 121 * triggerEvent 用于触发事件 122 */ 123 _cancelEvent(){ 124 //触发取消回调 125 this.triggerEvent("cancelEvent") 126 }, 127 _confirmEvent(){ 128 //触发成功回调 129 this.triggerEvent("confirmEvent"); 130 }, 131 bindChange(event){ 132 // 保存滚动按钮坐标 133 this.setData({ 134 areaList:event.detail.value 135 }) 136 if (this.data.provinceCode!=this.data.area.province[event.detail.value[0]].code) { 137 // 改动了省,修改省的代码 138 this.setData({ 139 provinceCode:this.data.area.province[event.detail.value[0]].code 140 }) 141 this.getCity(); 142 } 143 if (this.data.cityCode!=this.data.area.city[event.detail.value[1]].code) { 144 // 改动了省,修改省的代码 145 this.setData({ 146 cityCode:this.data.area.city[event.detail.value[1]].code 147 }) 148 this.getArea(); 149 } 150 if (this.data.areaCode!=this.data.area.area[event.detail.value[2]].code) { 151 // 改变了区的选择 152 this.setData({ 153 address:{ 154 province:this.data.area.province[event.detail.value[0]], 155 city:this.data.area.city[event.detail.value[1]], 156 area:this.data.area.area[event.detail.value[2]] 157 } 158 }) 159 } 160 }, 161 } 162 }) 163 164 165 // 使用说明使用在你需要此组件的文件中引入,引入方式如下 166 // wxml中引入方式 167 // <area id="area" bind:cancelEvent="_cancelEvent" bind:confirmEvent="_confirmEvent"></area> 168 // 其中_cancelEvent为取消按钮 169 // _confirmEvent为确认按钮 170 // js中定义方式 171 // this.area = this.selectComponent("#area"); 172 // 在json中定义方式 174 // "usingComponents": { 175 // "area": "/components/area/area" 176 // } 177 // } 178 // by张涛20180307
思路来源于以下文章
知识无止境,追其宗,而归一