需要实现的需求
- 数据渲染使用懒加载
- 点击任意一级都可返回,不需要一直点到最后一级
- 编辑或者查看功能,回显之前选择的数据
实例解析
dom 元素
<el-cascader
v-model="value"
:options="options"
:props="props"
:key="num"
@change="chaangeFunc"
ref="refHandle"
></el-cascader>
- value - 级联选择器绑定的数据
- options - 级联选择器列表数据
- props - 级联选择器配置内容
- num - 为级联选择器设置节点,后续在数据变化时,可以更新节点通知 DOM 更新
- chaangeFunc - 监听级联选择器的选择事件
模拟接口
// 模拟接口数据
// level:层级,key:用上一级查下一级参数使用的标识
getTempData(level, key) {
return new Promise((resolve, reject) => {
let result = []; // 最终要返回的数据
if (level == 1) {
// 一级的数据
result = [
{ label: "测试1", value: 1, level: 1 },
{ label: "测试2", value: 2, level: 1 },
];
}
if (level == 2) {
// 二级的数据
if (key == 1) {
// "测试1" 查回来的子数据
result = [
{ label: "测试1-1", value: 11, level: 2 },
{ label: "测试1-2", value: 12, level: 2 },
{ label: "测试1-3", value: 13, level: 2 },
];
}
}
if (level == 3) {
// 二级的数据
if (key == 11) {
// "测试1-1" 查回来的子数据
result = [
{ label: "测试1-1-1", value: 111, level: 3 },
{ label: "测试1-1-2", value: 112, level: 3 },
{ label: "测试1-1-3", value: 113, level: 3 },
];
}
}
setTimeout((item, index) => {
console.log("级联请求到的数据", result);
// 做一个延时,模拟接口数据返回
resolve(result);
}, 1000);
});
}
// 完整的数据结构
// [{
// label: "测试1",
// value: 1,
// children: [
// {
// label: "测试1-1",
// value: 11,
// children: [
// { label: "测试1-1-1", value: 111 },
// { label: "测试1-1-2", value: 112 },
// { label: "测试1-1-3", value: 113 },
// ],
// },
// { label: "测试1-2", value: 12 },
// { label: "测试1-3", value: 13 },
// ],
// },
// { label: "测试2", value: 2, children: [] },]
渲染数据
- 默认请求一级数据
// 默认请求一级数据
this.getTempData(1).then((dataLev1) => {
this.options = dataLev1;
});
- 级联选择器懒加载函数
checkStrictly
是否严格的遵守父子节点不互相关联
boolean
lazyLoad
加载动态数据的方法,仅在 lazy 为 true 时有效
function(node, resolve),node 为当前点击的节点,resolve 为数据加载完成的回调(必须调用)
props: {
checkStrictly: true, // 取消父节点与子节点的严格关联,可以任意选中任何一级作为结束
lazy: true,
lazyLoad: (node, resolve) => {
let result = node.data;
console.log("点击的节点数据", result);
if (result) {
if (result.level != 3) {
// 如果当前点击的不是第三级,则需要去调用接口查询数据
this.getTempData(Number(result.level) + 1, result.value).then(
(sourceData) => {
let data = [];
if (sourceData && sourceData.length > 0) {
data = sourceData;
}
// 将获取到的数据抛出
resolve(data);
}
);
} else {
resolve([]);
}
} else {
}
},
},
- 效果
- 默认渲染一级
- 点击请求二级
- 再点击请求三级
- 选中任意一级都能返回
- 默认渲染一级
// 如果需要在选中后关闭级联弹层,监听 change 事件即可
chaangeFunc() {
console.log("触发了change", this.value);
// 选中节点后,关闭下拉
this.$refs.refHandle.dropDownVisible = false;
}
数据回显
- 第一步,获取级联下拉列表的 options,不需要全部渲染,只需要渲染被选中的部分的那一条链路
- 第二步,为级联选择器绑定的 value 赋值
- 第三步,为最后一级添加 leaf 属性,告诉结构树此节点为末级节点
getDetail() {
let detailList = [1, 11, 111]; // 模拟获取到的需要渲染的节点数据
this.getTempData(1).then((dataLev1) => {
this.options = dataLev1;
console.log("渲染完了一级");
this.options.map((itemLev1, indexLev1) => {
if (itemLev1.value == detailList[0]) {
console.log("匹配到一级选中内容,开始查询二级");
this.getTempData(2, itemLev1.value).then((dataLev2) => {
if (dataLev2 && dataLev2.length > 0) {
console.log("查询到了二级数据,继续向下查询");
this.$set(itemLev1, "children", dataLev2);
console.log("渲染完了二级");
itemLev1.children.map((itemLev2, indexLev2) => {
if (itemLev2.value == detailList[1]) {
console.log("匹配到二级选中内容,开始查询三级");
this.getTempData(3, itemLev2.value).then((dataLev3) => {
if (dataLev3 && dataLev3.length > 0) {
console.log("查询到了三级数据,即最末为三级");
this.$set(itemLev2, "children", dataLev3);
itemLev2.children.map((itemLev3, indexLev3) => {
console.log("末级添加标志位");
itemLev3.leaf = "leaf";
});
} else {
console.log("未查询到三级数据,即最末为二级");
itemLev2.leaf = "leaf";
}
console.log("渲染完了三级");
this.value = detailList;
this.num += 1;
});
}
});
} else {
console.log("未查询到二级数据,即最末为一级");
itemLev1.leaf = "leaf";
}
this.value = detailList;
this.num += 1;
});
}
});
});
},
- 执行渲染数据的方法 getDetail
级联请求到的数据 (2) [{…}, {…}]
渲染完了一级
匹配到一级选中内容,开始查询二级
级联请求到的数据 (3) [{…}, {…}, {…}]
查询到了二级数据,继续向下查询
渲染完了二级
匹配到二级选中内容,开始查询三级
级联请求到的数据 (3) [{…}, {…}, {…}]
查询到了三级数据,即最末为三级
末级添加标志位
渲染完了三级
完整代码
<template>
<div class="activeEnroll_list">
<el-cascader
v-model="value"
:options="options"
:props="props"
:key="num"
@change="chaangeFunc"
ref="refHandle"
></el-cascader>
</div>
</template>
<script>
export default {
name: "activeEnroll_list",
components: {},
data() {
return {
num: 0,
value: [],
options: [
// {
// label: "测试1",
// value: 1,
// children: [
// {
// label: "测试1-1",
// value: 11,
// children: [
// { label: "测试1-1-1", value: 111 },
// { label: "测试1-1-2", value: 112 },
// { label: "测试1-1-3", value: 113 },
// ],
// },
// { label: "测试1-2", value: 12 },
// { label: "测试1-3", value: 13 },
// ],
// },
// { label: "测试2", value: 2, children: [] },
],
props: {
checkStrictly: true, // 取消父节点与子节点的严格关联,可以任意选中任何一级作为结束
lazy: true,
lazyLoad: (node, resolve) => {
let result = node.data;
console.log("点击的节点数据", result);
if (result) {
if (result.level != 3) {
this.getTempData(Number(result.level) + 1, result.value).then(
(sourceData) => {
let data = [];
if (sourceData && sourceData.length > 0) {
data = sourceData;
}
resolve(data);
}
);
} else {
resolve([]);
}
} else {
}
},
},
};
},
created() {},
mounted() {
let flag = true; // flag 控制是执行新增还是编辑
if (flag) {
// 是编辑
this.getDetail();
} else {
// 是新增
this.getTempData(1).then((dataLev1) => {
this.options = dataLev1;
});
}
},
watch: {},
computed: {},
methods: {
chaangeFunc() {
console.log("触发了change", this.value);
// 选中节点后,关闭下拉
this.$refs.refHandle.dropDownVisible = false;
},
// mock 接口数据
getTempData(level, key) {
return new Promise((resolve, reject) => {
let result = [];
if (level == 1) {
result = [
{ label: "测试1", value: 1, level: 1 },
{ label: "测试2", value: 2, level: 1 },
];
}
if (level == 2) {
if (key == 1) {
result = [
{ label: "测试1-1", value: 11, level: 2 },
{ label: "测试1-2", value: 12, level: 2 },
{ label: "测试1-3", value: 13, level: 2 },
];
}
}
if (level == 3) {
if (key == 11) {
result = [
{ label: "测试1-1-1", value: 111, level: 3 },
{ label: "测试1-1-2", value: 112, level: 3 },
{ label: "测试1-1-3", value: 113, level: 3 },
];
}
}
setTimeout((item, index) => {
console.log("级联请求到的数据", result);
resolve(result);
}, 1000);
});
},
getDetail() {
let detailList = [1, 11, 111]; // 模拟获取到的需要渲染的节点数据
this.getTempData(1).then((dataLev1) => {
this.options = dataLev1;
console.log("渲染完了一级");
this.options.map((itemLev1, indexLev1) => {
if (itemLev1.value == detailList[0]) {
console.log("匹配到一级选中内容,开始查询二级");
this.getTempData(2, itemLev1.value).then((dataLev2) => {
if (dataLev2 && dataLev2.length > 0) {
console.log("查询到了二级数据,继续向下查询");
this.$set(itemLev1, "children", dataLev2);
console.log("渲染完了二级");
itemLev1.children.map((itemLev2, indexLev2) => {
if (itemLev2.value == detailList[1]) {
console.log("匹配到二级选中内容,开始查询三级");
this.getTempData(3, itemLev2.value).then((dataLev3) => {
if (dataLev3 && dataLev3.length > 0) {
console.log("查询到了三级数据,即最末为三级");
this.$set(itemLev2, "children", dataLev3);
itemLev2.children.map((itemLev3, indexLev3) => {
console.log("末级添加标志位");
itemLev3.leaf = "leaf";
});
} else {
console.log("未查询到三级数据,即最末为二级");
itemLev2.leaf = "leaf";
}
console.log("渲染完了三级");
this.value = detailList;
this.num += 1;
});
}
});
} else {
console.log("未查询到二级数据,即最末为一级");
itemLev1.leaf = "leaf";
}
this.value = detailList;
this.num += 1;
});
}
});
});
},
},
};
</script>