基於elementUI的Cascader組件封裝的多功能地區區划選擇器(可回顯、接口懶加載)


注:公司領導要求封裝一個區划選擇器,最大支持五級區划,並且適用的場景有很多:數據全部由接口所得並且是懶加載形式;能夠回顯當前登錄賬號所屬級別的默認地址;還能夠回顯接口返回的默認地址;能夠配置區划選擇器的最大級別;禁止當前級別之前的地址被選擇等等功能,花了兩天的事時間,終於算是完善優化好了,供大家一起參考,代碼若有缺陷還望指針,感謝!以下是源代碼:

特別說明:這里面使用懶加載形式調取接口,每次接口返回一個級別的數據,如第一次默認返回所有省級,點擊安徽省,傳安徽省code則再次調用接口返回安徽省下所有地級市的數據,依次類推;這里接口返回的數組中,必須要有的參數:[{name:'級別名稱',id:'級別code值'}]

技術棧:VUE+ElementUI

組件areaCascader.vue

<template>
  <div>
    <el-tooltip
      effect="dark"
      :content="addressName"
      placement="top"
      :enterable="false"
      :disabled="disabled"
    >
      <el-cascader
        :disabled="casDisabled"
        :clearable="clearable"
        ref="areaSelect"
        v-model="areaCodeList"
        :props="belongRegoinProps"
        :options="belongRegoinOptions"
        placeholder="請選擇"
        @change="belongRegionChange"
        @visible-change="visibleChange"
        style="width: 100%"
      >
      </el-cascader>
    </el-tooltip>
  </div>
</template>

<script>
// 這里是我項目中自己封裝的get請求 各位可自己封裝 import { get } from "@/apis/apicommon"; export default { name: "areaCascader", components: {}, // 注意:isCurrentOrgDefaultArea與isPortDefaultArea不能同時為true props: { setLevel:{ type:Number, default:5 }, // true開啟默認回顯當前賬號所屬區划地址,為false時關閉回顯並且可選擇任意區划 isCurrentOrgDefaultArea: { type: Boolean, default: true, }, // 回顯指定區划地址的對象數據,必須為以下指定格式字段,切且注意該對象傳入時間必須在該組件初始化之前 defaultAddressInfos: { type: Object, // default:{ // addressName:"", // provinceCode:"", // cityCode:"", // countyCode:"", // streetCode:"", // communityCode:"", // level:"" // } }, // true開啟默認回顯指定區划地址,需必傳對象defaultAddressInfos,且與isCurrentOrgDefaultArea不能同時為true isPortDefaultArea: { type: Boolean, default: false, }, // 是否可清空已選,默認不可清空 clearable: { type: Boolean, default: false, }, casDisabled: { type: Boolean, default:false }, }, watch: {}, data() { const self = this; return { disabled: true, addressName: "", defaultHosuse: { province: "", city: "", area: "", town: "", vill: "", }, CurrentOrg: {}, currentLastLevelCode: "", CurrentLevel: Number, areaCodeList: [], currentOrgLevel: "", belongRegoinOptions: [], belongRegoinProps: { checkStrictly: true, lazy: true, lazyLoad(node, resolve) { setTimeout(() => { self.getAreaForLazyLoad(node, resolve); }, 100); }, }, }; }, created() { if (this.isCurrentOrgDefaultArea) { // 通過當前賬號所在區划回顯 this.getCurrentOrg(); } if (this.isPortDefaultArea) { // 通過指定區划回顯 this.getDefaultArea(); } }, methods: { visibleChange(val) { console.log(val); if (val) { this.disabled = true; } else if (!val && this.addressName) { this.disabled = false; } }, belongRegionChange(val) { let res = this.$refs.areaSelect.getCheckedNodes(); console.log(res); if (res && res.length > 0) { this.addressName = res[0].pathLabels[0] + (res[0].pathLabels[1] || "") + (res[0].pathLabels[2] || "") + (res[0].pathLabels[3] || "") + (res[0].pathLabels[4] || ""); let areaNameObject = { provinceName: res[0].pathLabels[0], cityName: res[0].pathLabels[1], countyName: res[0].pathLabels[2], streetName: res[0].pathLabels[3], communityName: res[0].pathLabels[4], }; let areaCodeObject = { provinceCode: res[0].path[0], cityCode: res[0].path[1], countyCode: res[0].path[2], streetCode: res[0].path[3], communityCode: res[0].path[4], }; let data = { areaNameObject, areaCodeObject, }; this.$emit("selectedAreaList", data); } else { this.addressName = ""; let areaNameObject = { provinceName: "", cityName: "", countyName: "", streetName: "", communityName: "", }; let areaCodeObject = { provinceCode: "", cityCode: "", countyCode: "", streetCode: "", communityCode: "", }; let data = { areaNameObject, areaCodeObject, }; this.$emit("selectedAreaList", data); this.disabled = true; } }, getAreaForLazyLoad(node, resolve) { const { level } = node; let data = {}; if (level == 0) { data = { areaCode: "000000", }; } else if ( level == 1 || level == 2 || level == 3 || level == 4 || level == 5 ) { data = { areaCode: node.value, }; } else { return false; }
// 這里是接口 get(
"/area/getNextAreaInfoByCode", data) .then((res) => { if (res.succeed) { let isContain = data.areaCode.search(this.currentLastLevelCode); let oData = []; // let oData = this.formatAreaData(res.data, level); if (this.isCurrentOrgDefaultArea || this.isPortDefaultArea) { let arrList = this.formatAreaData(res.data, level); arrList.map((item, index) => { if ( (item.level <= this.CurrentLevel && this.isCurrentOrgDefaultArea) || (data.areaCode !== this.currentLastLevelCode && this.CurrentLevel >= level) || isContain != 0 ) { oData.push(Object.assign({}, item, { disabled: true })); } else { oData.push(Object.assign({}, item, { disabled: false })); } }); } else { oData = this.formatAreaData(res.data, level); } // this.belongRegoinOptions = oData if (oData.length == 0) { // // console.log('子節點數據為空', node) // node.syncCheckState(node.value); // const checkedNode = this.$refs.areaSelect.getCheckedNodes(); // // console.log('獲得剛才選中的節點', checkedNode) // node.syncCheckState(node.value) // node.doCheck(true) // this.$set(node, 'leaf', true) // oData = undefined; // resolve(oData); // return; } resolve(oData); } }) .catch((err) => { console.log(err); this.$message.error(err); }); }, formatAreaData(data, level) { return data.map((item) => { item.names = item.name; item.value = item.id; item.label = item.name; item.leaf = level >= (this.setLevel - 1); return item; }); }, handleAreaCode() { let areaCodeList = []; if (this.defaultHosuse.province) { areaCodeList.push(this.defaultHosuse.province); this.currentLastLevelCode = this.defaultHosuse.province; } if (this.defaultHosuse.city) { areaCodeList.push(this.defaultHosuse.city); this.currentLastLevelCode = this.defaultHosuse.city; } if (this.defaultHosuse.area) { areaCodeList.push(this.defaultHosuse.area); this.currentLastLevelCode = this.defaultHosuse.area; } if (this.defaultHosuse.town) { areaCodeList.push(this.defaultHosuse.town); this.currentLastLevelCode = this.defaultHosuse.town; } if (this.defaultHosuse.vill) { areaCodeList.push(this.defaultHosuse.vill); this.currentLastLevelCode = this.defaultHosuse.vill; } this.areaCodeList = areaCodeList; console.log(areaCodeList); if (this.addressName == "") { this.disabled = true; } else { this.disabled = false; } }, getDefaultArea() { console.log(this.defaultAddressInfos); this.addressName = this.defaultAddressInfos.addressName; this.defaultHosuse.province = this.defaultAddressInfos.provinceCode || ""; this.defaultHosuse.city = this.defaultAddressInfos.cityCode || ""; this.defaultHosuse.area = this.defaultAddressInfos.countyCode || ""; this.defaultHosuse.town = this.defaultAddressInfos.streetCode || ""; this.defaultHosuse.vill = this.defaultAddressInfos.communityCode || ""; this.CurrentLevel = this.defaultAddressInfos.level; this.handleAreaCode(); }, getCurrentOrg() { get("/organization/getCurrentOrg", {}).then((res) => { if (res.succeed) { let data = res.data; this.addressName = (data.provinceName || "") + (data.cityName || "") + (data.countyName || "") + (data.streetName || "") + (data.communityName || ""); // this.currentOrgLevel = data.level; // this.CurrentOrg = data; // let {province='provinceCode',city='cityCode',area='countyCode',town='streetCode',vill='communityCode'} = data // this.defaultHosuse = {province='provinceCode',city='cityCode',area='countyCode',town='streetCode',vill='communityCode'} this.defaultHosuse.province = data.provinceCode; this.defaultHosuse.city = data.cityCode; this.defaultHosuse.area = data.countyCode; this.defaultHosuse.town = data.streetCode; this.defaultHosuse.vill = data.communityCode; this.CurrentLevel = data.level; this.handleAreaCode(); let areaNameObject = { provinceName: data.provinceName, cityName: data.cityName, countyName: data.countyName, streetName: data.streetName, communityName: data.communityName, }; let areaCodeObject = { provinceCode: data.provinceCode, cityCode: data.cityCode, countyCode: data.countyCode, streetCode: data.streetCode, communityCode: data.communityCode, }; let val = { areaNameObject, areaCodeObject, }; this.$emit("selectedAreaList", val); } }); }, }, }; </script> <style scoped> </style>

使用文件:index.vue

<template>
  <div>
    <el-form
      ref="tableData"
      :rules="rules"
      :model="tableData"
      label-width="130px"
      size="mini"
    >
      <el-row>
        <el-col :span="12">
          <el-form-item label="現常住地址:">
            <Area-cascader
              @selectedAreaList="selectedAreaList"
              :isCurrentOrgDefaultArea="false"
              :clearable="true"
            ></Area-cascader>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
  
  </div>
</template>

<script>
import { get, downloadFile, post } from "@/apis/apicommon";
import AreaCascader from "@/components/common/areaCascader.vue";
export default {
  name: "page1",
  components: {
    AreaCascader,
  },
  props: {
    
  },
  data() {
    return {
      formData: {},
    };
  },
  created() {

  },
  mounted() {},
  methods: {
    // 地址選中值
    selectedAreaList(val) {
      // 這里是返回的區划name和code,一共有五級
      console.log(val);
      let { provinceCode, cityCode, countyCode, streetCode, communityCode } =
        val.areaCodeObject;
      this.formData.province = provinceCode;
      this.formData.city = cityCode;
      this.formData.county = countyCode;
      this.formData.street = streetCode;
      this.formData.community = communityCode;
      let { provinceName, cityName, countyName, streetName, communityName } =
        val.areaNameObject;
      this.formData.provinceName = provinceName;
      this.formData.cityName = cityName;
      this.formData.countyName = countyName;
      this.formData.streetName = streetName;
      this.formData.communityName = communityName;
    },
  
  },
};
</script>
<style scoped>

</style>

多看一下封裝的組件里面各種配置項,尤其是區划的數據格式,這里的code和name一起封裝,如果有任何疑問歡迎留言!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM