element-plus el-cascader 懒加载实现-省市区街道选择及回显

大概思路:

  1. 准备一个接口可以通过父Id,查询到下一级省市区街道的信息;如下方的getRegionListOne
  2. 确定后端的数据结构,需要在created里边处理数据回显逻辑
  3. el-cascader接收的数据格式是'','','';后端的数据格式多为{provinceId: '', regionId: '', cityId: ''}
  4. 可以通过设置comType,来确定是省市区还是省市区街道,组件内完成逻辑处理。

直接上代码

js 复制代码
<template>
    <div class="areaLazy">
      <el-cascader
        v-model="currentChoose"
        v-bind="_options"
        :options="addressList"
        :disabled="_options.disabled"
        @change="handleChange"
      />
  </div>
</template>

<script>
export default {
  name: "addresscascaderlazy",
};
</script>

<script setup>
import { ref, computed, watch } from "vue";
import API from "@/api";

const emits = defineEmits([
  "update:modelValue"
]);

const props = defineProps({
  disabled: {
    //禁用
    type: Boolean,
    required: false,
    default: false,
  },
  options: {
    type: Object,
    default: () => {},
  },
  modelValue: {
    type: [Array, Object],
    default: () => ([]),
  },
});
let id = 0;
// 设置option默认值,如果传入自定义的配置则合并option配置项
const _options = computed(() => {
  const option = {
    name: "multipartFiles",
    comType: "provinceCityCountryRegion",
    props: {
      lazy: true,
      lazyLoad(node, resolve) {
        const { level, value } = node; // 获取当前node对象中的level, value属性
        getArea(level, value, resolve)
      },
    }
  };
  option.disabled = props.disabled;
  return Object.assign(option, props.options);
});
const levelTag = {
  "provinceCityCountryRegion": 3,
  "provinceCityCountry": 2,
  "provinceCity": 1,
}
const currentChoose = ref([]);
const addressList = ref([]);
const addressOrigin = ref({}); // 省市区数据

const handleChange = (val) => {
  console.log('handleChange', val)
  if (!val.length) {
    emits('update:modelValue', val)
    return
  }
  if (_options.value?.props?.multiple) {
    const arr = []
    val.forEach(item => {
      const obj = {}
      obj.provinceId = item[0]
      obj.provinceName = addressOrigin.value[0][item[0]]
      obj.cityId = item[1]
      obj.cityName = addressOrigin.value[1][item[1]]
      obj.regionId = item[2]
      obj.regionName = addressOrigin.value[2][item[2]]
      obj.streetId = val[3]
      obj.streetName = addressOrigin.value[3][val[3]]
      arr.push(obj)
    })
    emits('update:modelValue', arr)
  } else {
    const obj = {}
    obj.provinceId = val[0]
    obj.provinceName = addressOrigin.value[0][val[0]]
    obj.cityId = val[1]
    obj.cityName = addressOrigin.value[1][val[1]]
    obj.regionId = val[2]
    obj.regionName = addressOrigin.value[2][val[2]]
    obj.streetId = val[3]
    obj.streetName = addressOrigin.value[3][val[3]]
    emits('update:modelValue', obj)
  }
}

const getArea = (level, value, resolve) => {
  API.getRegionListOne({parentId: value}).then(async (res) => {
    addressOrigin.value[level] = {}
    const nodes = res.result.map(item => {
      addressOrigin.value[level][item.id] = item.name
      return {  
        value: String(item.id),
        label: item.name,
        leaf: level >= levelTag[_options.value?.comType],
      }
    })
    resolve(nodes)
  })
}

const created = () => {
  if (!props.modelValue) {
    return []
  }
  if (props.modelValue instanceof Array) {
    currentChoose.value = props.modelValue.map(item => {
      if (_options.value.comType === "provinceCityCountryRegion") {
        return [ item.provinceId, item.cityId, item.regionId, item.streetId ]
      }
      if (_options.value.comType === "provinceCityCountry") {
        return [ item.provinceId, item.cityId, item.regionId ]
      }
      return [ item.provinceId, item.cityId ]
    })
  } else {
    if (_options.value.comType === "provinceCityCountryRegion") {
      currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId, props.modelValue.streetId]
      return
    }
    if (_options.value.comType === "provinceCityCountry") {
      currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId, props.modelValue.streetId]
      return
    }
    currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId]
  }
}

// 省市区
// getaddressList();
watch(()=>props.modelValue, (val) => {
  created();
})

</script>

<style lang="less">
.areaLazy {
  .el-input__inner {
    min-width: 350px;
  }
}
</style>

再附一个非懒加载形式的

js 复制代码
<template>
    <div class="areaUnit">
      <el-cascader
        v-model="currentChoose"
        v-bind="_options"
        :options="addressList"
        :disabled="_options.disabled"
        @change="handleChange"
      />
  </div>
</template>

<script>
export default {
  name: "addresscascader",
};
</script>

<script setup>
import { ref, computed, watch } from "vue";
import API from "@/api";

const emits = defineEmits([
  "update:modelValue"
]);

const props = defineProps({
  disabled: {
    //禁用
    type: Boolean,
    required: false,
    default: false,
  },
  options: {
    type: Object,
    default: () => {},
  },
  modelValue: {
    type: [Array, Object],
    default: () => ([]),
  },
});

// 设置option默认值,如果传入自定义的配置则合并option配置项
const _options = computed(() => {
  const option = {
    name: "multipartFiles",
    comType: "provinceCityCountry",
  };
  option.disabled = props.disabled;
  return Object.assign(option, props.options);
});

const currentChoose = ref([]);
const addressList = ref([]);
const addressOrigin = ref({});
// 处理省市区数据结构
const handleBase = (list, childrenList, stringBan) => {
  return new Promise((resolve) => {
    const address = []
    if (childrenList) {
      for (const key in list) {
          const children = childrenList.filter(i => String(i.value).substring(0, stringBan) === String(key).substring(0, stringBan));
          address.push({
            value: key,
            label: list[key],
            children
          })
      }
    } else {
      for (const key in list) {
        address.push({
          value: key,
          label: list[key]
        })
      }
    }
    resolve(address)
  })
}

// 获取省市区
const getaddressList = () => {
  API.getRegionList().then(async (res) => {
    const { province_list, city_list, county_list } = res.result;
    addressOrigin.value = { province_list, city_list, county_list }
    if (_options.value.comType === "provinceCityCountry") {
      const countyAddress = await handleBase(county_list)
      const cityAddress = await handleBase(city_list, countyAddress, 4)
      addressList.value = await handleBase(province_list, cityAddress, 2)
    }
    if (_options.value.comType === "provinceCity") {
      const cityAddress = await handleBase(city_list)
      addressList.value = await handleBase(province_list, cityAddress, 2)
    }
  })
}
const handleChange = (val) => {
  if (!val.length) {
    emits('update:modelValue', val)
    return
  }
  if (_options.value?.props?.multiple) {
    const arr = []
    val.forEach(item => {
      const obj = {}
      obj.provinceId = item[0]
      obj.provinceName = addressOrigin.value.province_list[item[0]]
      obj.cityId = item[1]
      obj.cityName = addressOrigin.value.city_list[item[1]]
      obj.regionId = item[2]
      obj.regionName = addressOrigin.value.county_list[item[2]]
      arr.push(obj)
    })
    emits('update:modelValue', arr)
  } else {
    const obj = {}
    obj.provinceId = val[0]
    obj.provinceName = addressOrigin.value.province_list[val[0]]
    obj.cityId = val[1]
    obj.cityName = addressOrigin.value.city_list[val[1]]
    obj.regionId = val[2]
    obj.regionName = addressOrigin.value.county_list[val[2]]
    emits('update:modelValue', obj)
  }
}

const created = () => {
  if (!props.modelValue) {
    return []
  }
  if (props.modelValue instanceof Array) {
    currentChoose.value = props.modelValue.map(item => {
      if (_options.value.comType === "provinceCityCountry") {
        return [ item.provinceId, item.cityId, item.regionId ]
      }
      return [ item.provinceId, item.cityId ]
    })
  } else {
    if (_options.value.comType === "provinceCityCountry") {
      currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId, props.modelValue.regionId]
    } else {
      currentChoose.value = [props.modelValue.provinceId, props.modelValue.cityId]
    }
  }
}

// 省市区
getaddressList();
watch(()=>props.modelValue, (val) => {
  console.log('modelValue', val)
  created();
})
</script>
相关推荐
Python自动化直播31 分钟前
智能脚本批量管理拆开看:导入、导出、重写、试听
前端·python·ai·秒播
开开心心就好1 小时前
发票信息录入太麻烦?离线工具一键转表格
运维·服务器·前端·pdf·ocr·maven·intellij-idea
এ慕ོ冬℘゜1 小时前
ES Promise.all/ Promise.race
前端·javascript·elasticsearch
喜欢打篮球的普通人2 小时前
LLVM 前端与优化层:Clang 如何把 C 代码变成 IR
c语言·前端·状态模式
只睡四小时3 小时前
端侧推理:face-api.js 首屏 92% 是白下载的
开发语言·javascript·人脸识别·ecmascript·tensorflow.js·face-api.js·端侧推理
大文说跨境3 小时前
亚马逊多店铺用过多款指纹浏览器,说点长期用的实际感受
前端·网络
中屹指纹浏览器svip3 小时前
中屹指纹浏览器和普通 Chrome 有什么区别?
前端·chrome·中屹指纹浏览器
feixing_fx3 小时前
CSS Grid 入门:二维布局时代的降维打击
前端·css·前端框架·css3
Lank_M3 小时前
JPG的8×8块里只要有条边,白底就保不住255
前端