1. 程式人生 > 其它 >小程式開發的省市區自定義元件

小程式開發的省市區自定義元件

技術標籤:微信開發前端小程式weui

最近公司一個專案需要做小程式開發。其中有一個表單項需要省市區選擇。網上找了一圈後,借鑑能人程式碼,自己小小加工完善一下,做了一個自定義元件。廢話不多數,上程式碼,使用了小程式的picker多列選擇器:

首先是元件部分:

wxml:

<view class="section">
  <picker mode="multiSelector" disabled="{{disabled}}" bindchange="bindMultiPickerChange" width="100%" bindcolumnchange="bindMultiPickerColumnChange" value="{{multiIndex}}" range="{{multiArray}}" range-key="name">
    <view class="weui-input" wx:if="{{showView}}">
      {{multiArray[0][multiIndex[0]].name}}{{multiArray[1].length > 0 ?("," + multiArray[1][multiIndex[1]].name):""}}{{multiArray[2].length > 0 ?("," + multiArray[2][multiIndex[2]].name):""}}
      <text decode="true">&nbsp;&nbsp;</text><mp-icon wx:if="{{showClear}}" icon="close2" catchtap="clearPicker" color="#696969" size="{{20}}"></mp-icon>
    </view>
    <view class="weui-input" wx:if="{{!showView}}">
      請選擇
    </view>
  </picker>
</view>

js:

// pages/component/citySelecter.js
var cityUtil = require("../data/cityDataArr");
Component({
  observers: {
    'province, city, county': function(province, city, county) {
      // 監聽屬性變化 
      this.getCityInfo()
    }
  },
  /**
   * 元件的屬性列表
   */
  properties: {
    province:String,//省程式碼
    city:String,//市程式碼
    county:String,//地區程式碼
    clearable: { // 是否可清空,預設不帶清空按鈕
      type: Boolean,
      value: false
    },
    disabled: { // 是否禁用,false為啟用
      type: Boolean,
      value: false
    }
  },

  /**
   * 元件的初始資料
   */
  data: {
    showView: true,
    provinces: {},
    multiArray: [],
    multiIndex: [0,0,0],
    disabled:false,
    showClear:false
  },
  lifetimes: {
    // 生命週期函式,可以為函式,或一個在methods段中定義的方法名
    ready: function () { 
      this.getCityInfo()
    }
  },
  /**
   * 元件的方法列表
   */
  methods: {
    //獲取資料庫資料
    getCityInfo: function(){
      //獲取本地資料
      this.setData({
        showClear:this.properties.clearable,
        disabled:this.properties.disabled
      })
      
      var temp = cityUtil.cityArray.data;
      //初始化預設選中專案
      var defprovince = this.properties.province
      var provinceIndex=18
      var defcity=this.properties.city
      var cityIndex=3
      var defcoutry=this.properties.county
      var countyIndex=0
      //console.log(defprovince+","+defcity+","+defcoutry)
      
      if(!defprovince||!defcity||!defcoutry)
      {
        //未設定時,設空值
        this.setData({showView:false})
      }else{
        this.setData({showView:true})
        for(var i=0;i<temp.length;i++)
        {
          if(temp[i].code==defprovince)
          {
            provinceIndex=i
            for(var j=0;j<temp[i].citys.length;j++)
            {
              if(temp[i].citys[j].code==defcity)
              {
                cityIndex=j
                for(var k=0;k<temp[i].citys[j].areas.length;k++)
                {
                  if(temp[i].citys[j].areas[k].code==defcoutry){
                    countyIndex=k
                  }
                }
              }
            }
          }
        }
      }
      this.setData({
        provinces: temp,
        multiArray: [temp, temp[provinceIndex].citys, temp[provinceIndex].citys[cityIndex].areas],
        multiIndex: [provinceIndex, cityIndex, countyIndex]
      })
      // console.log(this.data.provinces)
    },
    clearPicker:function(e){
      //傳給父元件處理清空事件
      var clearEventDetail={};
      var clearEventOption={};
      this.triggerEvent('clearSelect', clearEventDetail, clearEventOption);
    },
    //點選確定
    bindMultiPickerChange: function (e) {
      // console.log('picker傳送選擇改變,攜帶值為', e.detail.value)
      var Indexs=e.detail.value;
      this.setData({
        multiIndex: Indexs,
        showView:true
      });
      //繫結自定義事件,給父元件傳參
      var temp = this.data.multiArray;
      //code 陣列
      var codes = []
      var names = []
      if(temp[2].length>0){
        codes = [temp[0][Indexs[0]].code, temp[1][Indexs[1]].code, temp[2][Indexs[2]].code]
        names = [temp[0][Indexs[0]].name, temp[1][Indexs[1]].name, temp[2][Indexs[2]].name]
      }
      else{
        codes = [temp[0][Indexs[0]].code, temp[1][Indexs[1]].code, temp[1][Indexs[1]].code]
        names = [temp[0][Indexs[0]].name, temp[1][Indexs[1]].name, temp[1][Indexs[1]].name]
      }

      //name 陣列
      //var names = [temp[0][Indexs[0]].name, temp[1][Indexs[1]].name, temp[2][Indexs[2]].name]
      var myEventDetail={codes, names};
      var myEventOption={};
      this.triggerEvent('selectCity', myEventDetail, myEventOption);
    },
    //滑動
    bindMultiPickerColumnChange: function(e){
      //console.log('修改的列為', e.detail.column, ',值為', e.detail.value);
      var data = {
        multiArray: this.data.multiArray,
        multiIndex: this.data.multiIndex
      };
      //更新滑動的第幾列e.detail.column的陣列下標值e.detail.value
      data.multiIndex[e.detail.column] = e.detail.value;
      //如果更新的是第一列“省”,第二列“市”和第三列“區”的陣列下標置為0
      if (e.detail.column == 0){
        data.multiIndex = [e.detail.value,0,0];
      } else if (e.detail.column == 1){
        //如果更新的是第二列“市”,第一列“省”的下標不變,第三列“區”的陣列下標置為0
        data.multiIndex = [data.multiIndex[0], e.detail.value, 0];
      } else if (e.detail.column == 2) {
        //如果更新的是第三列“區”,第一列“省”和第二列“市”的值均不變。
        data.multiIndex = [data.multiIndex[0], data.multiIndex[1], e.detail.value];
      }
      var temp = this.data.provinces;
      data.multiArray[0] = temp;
      if ((temp[data.multiIndex[0]].citys).length > 0){
        //如果第二列“市”的個數大於0,通過multiIndex變更multiArray[1]的值
        data.multiArray[1] = temp[data.multiIndex[0]].citys;
        var areaArr = (temp[data.multiIndex[0]].citys[data.multiIndex[1]]).areas;
        //如果第三列“區”的個數大於0,通過multiIndex變更multiArray[2]的值;否則賦值為空陣列
        data.multiArray[2] = areaArr.length > 0 ? areaArr : [];
      }else{
        //如果第二列“市”的個數不大於0,那麼第二列“市”和第三列“區”都賦值為空陣列
        data.multiArray[1] = [];
        data.multiArray[2] = [];
      }
      //data.multiArray = [temp, temp[data.multiIndex[0]].citys, temp[data.multiIndex[0]].citys[data.multiIndex[1]].areas];
      //setData更新資料
      this.setData(data);
    }
  }
})

json:

{
  "component": true,
  "usingComponents": {
    "mp-icon": "weui-miniprogram/icon/icon"
  }
}

wxss:

.picker{
  padding: 13px;
  background-color: #FFFFFF;
}

然後是使用元件的wxml部分:

<mp-rangePicker id="oAddressPicker" province="{{oAddressProvince}}" city="{{oAddressCity}}" county="{{oAddressCounty}}" bindclearSelect="clearSelectedOAddr" bindselectCity="SelectCitysOaddr" clearable="true">
            </mp-rangePicker>

js事件:

clearSelectedOAddr:function(e){
    this.setData({
      oAddressProvince:null,
      oAddressCity:null,
      oAddressCounty:null,
      [`formData.oAddressProvince`]: null,
      [`formData.oAddressCity`]: null,
      [`formData.oAddressCounty`]: null,
      [`formData.addressOther`]: null
    })
  },
SelectCitysOaddr(e){
    // console.log('SelectCitys事件', e.detail.param1)
    this.setData({
      [`formData.oAddressProvince`]: e.detail.codes[0],
      [`formData.oAddressCity`]: e.detail.codes[1],
      [`formData.oAddressCounty`]: e.detail.codes[2],
      [`formData.addressOther`]: e.detail.names[0]+e.detail.names[1]+e.detail.names[2]
    });
  }

效果,可選擇地區,獲取地區程式碼和名稱,可清空選擇:

另外,三級列表的資料來源如下格式,需要請留郵箱:

varcityArr={"data":[{"citys":[{"areas":[{"code":"110101","level":0,"name":"\u4e1c\u57ce\u533a","parent":"110100"},{"code":"110102","level":0,"name":"\u897f\u57ce\u533a","parent":"110100"},{"code":"110105","level":0,"name":"\u671d\u9633\u533a","parent":"110100"},{"code":"110106","level":0。。。。。。