基于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