虚拟列表怎么滚动到对应的node节点呢?scrollIntoView仅仅针对界面上DOM已经渲染的情况

虚拟列表怎么滚动到对应的node节点呢?scrollIntoView仅仅针对界面上DOM已经渲染的情况。

1、先来看看scrollIntoView生效条件

首先要确保 scrollIntoView 在虚拟列表中正确生效,需要确保在调用 scrollIntoView 时目标节点已经被渲染到 DOM中。由于虚拟列表(如 Ant Design 的 Tree 组件)是按需加载节点的,因此直接调用 scrollIntoView 可能会失败

2、再来看看虚拟列表的介绍

虚拟列表是一种优化长列表渲染性能的技术,特别适用于需要展示大量数据的场景。它通过仅渲染用户当前视窗内和附近的元素来减少DOM节点的数量,从而显著提高渲染性能和用户体验。这种技术广泛应用于滚动列表、表格和树形结构等组件中。

3、虚拟列表的核心原理

惰性加载 (Lazy Loading): 只加载和渲染用户视窗内的项目。随着用户滚动,动态加载新的项目并卸载超出视窗范围的项目。 窗口化
(Windowing): 将整个数据集分成多个窗口,每个窗口只包含一部分数据。仅渲染当前视窗及其前后几个窗口的内容。

4、虚拟列表的实现,虚拟列表的实现方式主要包括以下几种

固定高度/宽度: 假设每个列表项的高度或宽度是固定的,利用这个假设快速计算需要渲染的项目。 优点:实现简单,性能好。
缺点:列表项的高度或宽度必须一致。 动态高度/宽度: 列表项的高度或宽度可以不同,需要在滚动时动态计算每个项目的位置和尺寸。
优点:适应不同尺寸的列表项。 缺点:实现复杂度高,性能相对固定高度差一些。

5、常见虚拟列表库

以下是一些常用的虚拟列表库和框架,它们提供了开箱即用的虚拟化解决方案: React Virtualized:
提供了高性能的窗口化和惰性加载解决方案,支持表格、列表、网格等多种组件。 React Window: 比 React Virtualized
更轻量,专注于简单列表和网格的虚拟化。 Ant Design: Ant Design 的 Tree 组件支持虚拟列表,通过 virtual
属性启用。

不绕弯子了, 标题虚拟列表怎么滚动到对应的node节点呢。我们通过计算节点所在的index位置,让虚拟树所在的外层容器滚动index*height即可实现了。

 // 平铺展开的节点,找到目标node的下标
 const flattenNodes = flattenTreeData(newTreeData, newExpandKeys)
  const index = flattenNodes.findIndex(node => {
      if (node.key === tableNode.key) {
          return true;
      }
      return false;
  });
  if (index !== -1) {
      const element = document.querySelector(`.x-virtual-list`)
      if (element) {
          setTimeout(() =>{
              element.scrollTop = Math.max(0, (index - 4) * 36);
              console.log('scrollContainer.scrollTop:', element.scrollTop);
          }, 100)
      }
  }

//  treeNodeList为虚拟树的treeData . expandedKeys为展开了哪些节点
export const flattenTreeData = (treeNodeList = [], expandedKeys = []) => {
    const expandedKeySet = new Set(expandedKeys);
    const flattenList = [];

    const dig = (list, parent = null) => {
        return list.map((treeNode, index) => {
            // 内部记录的key值,用于记录节点层级关系和位置,拖拽时判断节点位置
            const pos = getPosition(parent ? parent.pos : '0', index);
            const mergedKey = getKey(treeNode.key, pos);

            const flattenNode = {
                ...treeNode,
                parent,
                pos,
                children: [],
                data: treeNode,
            };

            flattenList.push(flattenNode);

            if (expandedKeySet.has(mergedKey)) {
                flattenNode.children = dig(treeNode.children || [], flattenNode);
            } else {
                flattenNode.children = [];
            }

            return flattenNode;
        });
    };

    dig(treeNodeList);

    return flattenList;
};

/**
 * 获取节点的位置
 *
 * @param {string|number} level - 节点层级
 * @param {number} index - 节点在层级中的索引
 * @returns {string} 节点的位置
 */
export const getPosition = (level, index) => {
    return `${level}-${index}`;
};

/**
 * 获取节点的键
 *
 * @param {*} key - 节点的键
 * @param {string} pos - 节点的位置
 * @returns {*} 节点的键或位置
 */
export const getKey = (key, pos) => {
    if (key !== null && key !== undefined) {
        return key;
    }
    return pos;
};```



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值