引言

  • ant-design-vue 1.x与2.x版本中的a-tree组件不支持虚拟滚动,所以在加载大数据量场景下会造成页面渲染卡顿卡死现象,但在ant-design-vue 3.x版本后使用 height 属性则切换为虚拟滚动。当然,升级版本兼容性问题可能带来更大的工作量,所以这里推荐一个第三方插件vue-virt-list来解决大数据量卡顿问题

虚拟列表的核心原理

  • 可视区域渲染(视窗技术)
  • 动态计算渲染范围与位置
  • 减少 DOM 节点数量的优化机制

vue-virt-list 的特性

  • 轻量级与高性能、满帧率、百万数据
  • vue2与 Vue 3 的兼容性
  • 丰富的自定义配置选项
  • vue虚拟列表  [vue-virtual-list]
  • vue虚拟滚动列表[vue-virtual-scroll-list]
  • vue虚拟树 [vue-virt-tree]

安装与基本使用

  • 通过 npm 安装
npm install vue-virt-list -S
  • vue-virt-tree基础代码示例
<script lang="ts" setup>
import { onMounted, ref, shallowRef } from 'vue';
import { VirtTree } from 'vue-virt-list';
import 'vue-virt-list/lib/assets/tree.css';

type Data = {
  id: string | number;
  title: string;
  children?: Data;
}[];

const customFieldNames = {
  key: 'id',
};

const list = shallowRef<Data>([]);
onMounted(() => {
  list.value = Array.from({ length: 40 }).map((_, i) => ({
    id: String(i),
    title: `Node-${i}`,
    children: Array.from({ length: 3 }).map((_, index) => ({
      id: `${i}-${index}`,
      title: `Node-${i}-${index}`,
      children: Array.from({ length: 2 }).map((_, indexChild) => ({
        id: `${i}-${index}-${indexChild}`,
        title: `Node-${i}-${index}-${indexChild}`,
      })),
    })),
  }));
});

const virtTreeRef = ref<typeof VirtTree>();
</script>

<template>
  <div class="demo-tree">
    <div class="virt-tree-wrapper">
      <VirtTree
        ref="virtTreeRef"
        :list="list"
        :fieldNames="customFieldNames"
        :indent="20"
        expandOnClickNode
      >
        <template #empty>
          <div style="padding: 16px">暂无数据</div>
        </template>
      </VirtTree>
    </div>
  </div>
</template>

<style scoped lang="scss">
.demo-tree {
  width: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .tree-btn-container {
    display: flex;
    flex: 1;
    flex-direction: row-reverse;
    justify-content: space-between;
    padding: 12px 8px;
    gap: 8px;
    .input-label {
      font-size: 14px;
    }
    .btn-item {
      padding: 4px 12px;
      cursor: pointer;
      border: 1px solid #ececec;
      border-radius: 4px;
      font-size: 14px;
    }
    .input-container {
      display: flex;
      gap: 8px;
      align-items: center;
      input {
        height: 100%;
        border: 1px solid #ececec;
        border-radius: 4px;
        padding: 0 8px;
      }
    }
  }
}
</style>

官方参考文档 vue-virt-list | vue-virt-list

注意2点:

  1. 浏览器对于body高度是有最大限制的,当网页高度超出16777200px后无法显示后续内容。经过测试,数据大致在37万条后,就无法再显示后续内容。

  2. 使用大量数据的时候,建议使用 shallowRef 来声明list,减少响应式数据内存的暴增

插槽使用 注意事项

如果tree中每条数据需要操作时请使用content插槽,因为使用default插槽会变成列表模式默认全收起且无展开操作按钮,需要调用内置方法进行展开或收起

<template>
  <div class="demo-tree">
    <div class="virt-tree-wrapper">
      <VirtTree
        ref="virtTreeRef"
        :list="list"
        :fieldNames="customFieldNames"
        :indent="30"
      >
        <template #content="{ node }">
           <div> 
              <div>
                <span>level: {{ node.level }}; </span>
                <span>title: {{ node.data.name }}</span>
              </div>
              <div class="item-option">
				<a-icon type="EditOutlined" />
			  </div>
           </div>
        </template>

        <template #empty>
          <div style="padding: 16px">暂无数据</div>
        </template>
      </VirtTree>
    </div>
  </div>
</template>

github源:https://github.com/kolarorz/vue-virt-list

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐