antd虚拟滚动树图结合筛选实现

背景:

由于树图数量大的时候,会变得卡顿,因此需要开启虚拟滚动。

  1. 虚拟滚动的树图,又必须全量展示数据。
  2. 需要通过筛选,限制了全量展示数据。

因此,这两者存在矛盾,需要通过代码,较为友好的兼容。

注: 之前试过把不需要的进行隐藏,但是最终发现,依旧存在卡顿现象。

步骤:

  1. 树图开启虚拟滚动
ts 复制代码
<Tree virtual>
  1. 节点注入额外数据rootString,方便后续的判断 对树图的每个节点进行额外的注入,得到treeList
ts 复制代码
const formatData = (data: TreeItem[], rootString: string[]) => {
  for (let i = 0; i < data?.length; i++) {
    const node = data[i];
    const { title } = node;
    const _rootString = cloneDeep(rootString);
    _rootString.push(title);
    data[i].rootString = _rootString;
    dataList.push({ ...node, rootString: _rootString });
    if (node.children) {
      formatData(node.children, _rootString);
    }
  }
};
formatData(treeData.tree, []);
setTreeList(treeData.tree);
setShowDataList(dataList);
  1. 过滤筛选值 3.1. 通过rootString,找出符合名字的对应子节点,并在找子节点过程中,通过递归函数findAndPushByKey把父节点找出,把父节点注入showDataList 3.2 在执行3.1的过程中,需要考虑以下问题

全量数据

markdown 复制代码
├── 全国
    └── 广东
    │   ├── 广州
    │   └── 深圳
    └── 北京

子节点跟父节点均为树节点,如果查询广东,新拼接的树图,则为

筛选后的树图

markdown 复制代码
├── 全国
    └── 广东
        ├── 广州
        └── 深圳

此时,如果勾选根目录广东,树图组件会默认将全部key勾选【全国广东广州深圳】,以至于,取消查询时,由于存在全国这个key,所以antd展示会是全部树图勾选,也就是勾选项展示为4项,但是树图勾选为5项。

因此,此时需要将查询项往上的父节点,进行特殊标记,方便后面过滤不展示。因此,递归函数findAndPushByKey加入判断

ts 复制代码
if (!item.key.includes('temp-') && include === false) {
  // 临时拼进去的节点
  item.key = `temp-${item.key}`;
}
return item;

3.3 得到树图打平后的结构showDataList

  1. 渲染树图 执行方法renderTreeNodes通过treeList然后过滤出showDataList里面需要渲染的树图
ts 复制代码
const renderTreeNodes = useCallback(
  (data: TreeItem[]) => {
    const nodeArr = data?.map((item: TreeItem) => {
      valueMapKey[item.value] = item.key;
      if (item?.children) {
        return (
          <TreeNode
            style={{ height: '100%', display: '' }}
            title={
              <>
                <Tag color="volcano">{item?.pathName}</Tag>
                {item?.title}
              </>
            }
            key={item?.key}
            // @ts-ignore
            powerUserIds={item?.properties?.powerUserIds?.split(',') || []}
          >
            {renderTreeNodes(item?.children)}
          </TreeNode>
        );
      }
      return (
        <TreeNode
          title={
            <>
              <Tag color="volcano">{item?.pathName}</Tag>
              {item?.title}
            </>
          }
          key={item?.key}
          // @ts-ignore
          powerUserIds={item?.properties?.powerUserIds?.split(',') || []}
        />
      );
    });
    return nodeArr;
  },
  [valueMapKey],
);
  1. 判断树图 执行onCheck方法, noIncludeKey: 得到原有树图有的keys,但是现有树图未包含的keys。这些需要一直推进去 relateKeysrelateKeys: 关联的树图,这部分需要后端传参做特殊处理 keys: 这里跟3.2 联动,找到temp-开头的则不注入
js 复制代码
const onCheck = (
  keys: string[],
  info: { checked: boolean; node: { powerUserIds: string[] } },
) => {
  // 未包含在勾选里面的keys值,持续放进去
  const noIncludeKey = checkedKeysValue.filter(
    (keys) => showDataList.findIndex((data) => data.key === keys) === -1,
  );
  /** 匹配的关联keys */
  const relateKeys = info.checked
    ? info.node.powerUserIds.map((item: string) => valueMapKey[item])
    : [];
  const relateAccount = info.checked ? getRelateAccount(getTreeData, relateKeys) : [];
  setCheckedKeysValue([
    ...new Set([
      ...noIncludeKey,
      ...keys.filter((item) => !item.includes('temp-')),
      ...relateKeys,
      ...relateAccount,
    ]),
  ]);
};
相关推荐
秦jh_13 分钟前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑21325 分钟前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy26 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
涔溪1 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun2 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇2 小时前
ES6进阶知识一
前端·ecmascript·es6
渗透测试老鸟-九青2 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss