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>
相关推荐
zqx_717 分钟前
随记 前端框架React的初步认识
前端·react.js·前端框架
惜.己34 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
什么鬼昵称1 小时前
Pikachu-csrf-CSRF(get)
前端·csrf
长天一色1 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2342 小时前
npm、yarn、pnpm之间的区别
前端·npm·node.js
秋殇与星河2 小时前
CSS总结
前端·css
NiNg_1_2342 小时前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦2 小时前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
BigYe程普2 小时前
我开发了一个出海全栈SaaS工具,还写了一套全栈开发教程
开发语言·前端·chrome·chatgpt·reactjs·个人开发
神之王楠2 小时前
如何通过js加载css和html
javascript·css·html