Vue3 hooks 实现 el-tree懒加载反显问题

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;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值