el-cascader对于懒加载有支持方法,小难点在于回显的时候,由于懒加载第一次只有一层,所以要根据选中id数组一层层的加载。
子组件
<template>
<el-cascader
ref="cascaderRef"
v-model="selectedValue"
:props="CascaderProps"
:disabled="disabled"
style="width: 500px"
/>
</template>
<script setup>
import { ref, onMounted, defineEmits } from "vue";
import { ElCascader } from "element-plus";
import { listByParent, listParentByChild } from "@/api/common.js";
const cascaderRef = ref();
const props = defineProps({
modelValue: [String, Number],
disabled: {
type: Boolean,
default: false,
},
});
const selectedValue = ref([]); // 选中的id数组
const emit = defineEmits(["update"]); // 更新父组件的值
const CascaderProps = {
lazy: true, // 懒加载
checkStrictly: true, // 选择任意一项
lazyLoad(node, resolve) {
const { level, pathValues } = node;
listByParent({
adiId: node.value,
}).then((res) => {
const nodes = res.data.map((item) => {
return {
...item,
label: item.name,
value: item.adiId,
leaf:
(pathValues[0] == "330000000000" && level == 4) ||
(pathValues[0] != "330000000000" && level == 2)
? true
: false, // 浙江地区层级和别的省层级不一样,true表示最后一层
};
});
resolve(nodes);
});
},
};
// 回显逻辑
onMounted(async () => {
selectedValue.value = []; // 重置
setTimeout(async () => {
// 延迟执行
if (props.modelValue) {
// 存在值
let ids = await listParentByChild({
type: 1,
childAdiId: props.modelValue,
}); // 获取父级id数组
ids = ids.data.map((item) => item.adiId);
selectedValue.value = ids.reverse(); // 调换顺序,省市区顺序
await resolveCascaderNodes(selectedValue.value);
}
}, 1000);
});
// 递归解析路径
const resolveCascaderNodes = async (ids) => {
const nodes = [];
let currentParent = "";
// 加载子节点路径
for (const id of ids) {
const children = await listByParent(currentParent);
const target = children.data.find((item) => item.id === id);
if (target) {
nodes.push(target);
currentParent = id;
}
}
return nodes;
};
// 监听值变化
watch(selectedValue, (val) => {
if (val.length) emit("update", val[val.length - 1]);
});
</script>
父组件
<AreaCascader
:key="new Date().getTime()"
:disabled="disabled"
:modelValue="form.concatAddress"
@update="update"
/>
key是为了每次使用都刷新,不加不会每次调用onMounted里的方法
form.concatAddress的值是最后一个区划id,在子组件里面要用接口获取到完整的id数组
import AreaCascader from "@/components/Cascader/index.vue";
const update = (val) => {
form.value.concatAddress = val;
};
记录一下