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>
相关推荐
桂月二二4 小时前
探索前端开发中的 Web Vitals —— 提升用户体验的关键技术
前端·ux
CodeClimb5 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
沈梦研5 小时前
【Vscode】Vscode不能执行vue脚本的原因及解决方法
ide·vue.js·vscode
hunter2062065 小时前
ubuntu向一个pc主机通过web发送数据,pc端通过工具直接查看收到的数据
linux·前端·ubuntu
qzhqbb5 小时前
web服务器 网站部署的架构
服务器·前端·架构
刻刻帝的海角5 小时前
CSS 颜色
前端·css
轻口味5 小时前
Vue.js 组件之间的通信模式
vue.js
浪浪山小白兔6 小时前
HTML5 新表单属性详解
前端·html·html5
lee5767 小时前
npm run dev 时直接打开Chrome浏览器
前端·chrome·npm
2401_897579657 小时前
AI赋能Flutter开发:ScriptEcho助你高效构建跨端应用
前端·人工智能·flutter