import { nextTick, ref } from "vue";
/**
* el-tree + 懒加载 + 反显 hooks
* 思路:
* 注: 状态指 复选框状态
* 属性指 data 里面存储的 checkStatus
* 1、点击节点时触发 elTree 的 load 回调,load 里面去请求获取节点接口,接口完成时 触发 reviewTree
* 2、reviewTree 内部根据 返回的子节点状态属性 以及 当前父节点的状态 设置本次加载出来的子节点的状态(父节点状态优先级 高于 后端返回的子节点状态)
* 3、然后 触发 filter 设置所有节点状态
* 4、改变节点复选框的选中状态时触发 elTree 的 checked 回调
* 5、checked 回调内部调用 filter 遍历所有节点,根据状态设置所有节点的属性(indeterminate 为 true 就设置为半选,因为有时候会出现 checked 为 fasle 的情况)
* 6、getCheckedNodes 里面直接调 el-tree 的回调就行,el的回调会返回全选和半选的节点的 data 的集合
* @returns
*/
const useElTree = () => {
const myTree = ref();
const checkedNodes = ref([]);
const ALL_CHECKED = "2";
const SOME_CHECKED = "1";
const NO_CHECKED = "0";
const NONE_STATUS = "null";
// 设置ref
const setRef = (el) => {
myTree.value = el;
};
// 复选框点击回调
const checked = (node, nodes) => {
myTree.value.filter("check");
};
// 筛选所有节点 即 遍历所有节点
const filterNode = (value, data, node) => {
if (value === "check") setNumForStatus(node);
if (value === "load") initNode(node, NONE_STATUS);
if (value === "get") getNodes(data);
return true;
};
// 根据状态设置属性
const setNumForStatus = (node) => {
if (node.indeterminate) {
node.data.checkedStatus = SOME_CHECKED;
} else if (node.checked) {
node.data.checkedStatus = ALL_CHECKED;
} else {
node.data.checkedStatus = NO_CHECKED;
}
};
// 设置子节点以及本身状态
const reviewTree = (node) => {
nextTick(() => {
node.childNodes.forEach((n) => {
initNode(n, node.level === 0 ? NONE_STATUS : node.data.checkedStatus);
});
myTree.value.filter("load");
});
};
// 根据属性设置状态
const initNode = (node, parentStatus) => {
// 根据父节点状态 父节点全选则子节点全选 父节点全不选则子节点全不选 半选不影响
if (parentStatus === NONE_STATUS || parentStatus === SOME_CHECKED) {
switch (node.data.checkedStatus) {
case SOME_CHECKED:
node.checked = true;
node.indeterminate = true;
break;
case ALL_CHECKED:
node.checked = true;
node.indeterminate = false;
break;
default:
node.checked = false;
node.indeterminate = false;
}
} else if (parentStatus === ALL_CHECKED) {
node.checked = true;
node.indeterminate = false;
node.data.checkedStatus = ALL_CHECKED;
} else {
node.checked = false;
node.indeterminate = false;
node.data.checkedStatus = NO_CHECKED;
}
};
// 获取选中(全选 && 半选)的节点
const getCheckedNodes = () => {
checkedNodes.value.splice(0);
myTree.value.filter("get");
return checkedNodes.value;
};
// 获取全选和半选的节点
const getNodes = (data) => {
if (data.checkedStatus === ALL_CHECKED || data.checkedStatus === SOME_CHECKED) {
checkedNodes.value.push(data);
}
};
return [setRef, getCheckedNodes, reviewTree, checked, filterNode];
};
export default useElTree;
Vue3 hooks 实现 el-tree懒加载反显问题
最新推荐文章于 2024-07-20 16:46:53 发布