npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

virtual-tree-component

v2.0.0

Published

A virtual tree component for Vue.js

Readme

Vue Virtual Tree Component

基于 Element UI Tree 组件改造的虚拟滚动树组件,支持大数据量高效渲染。

功能特性

核心功能

  • 虚拟滚动:支持大数据量(10万+节点)高效渲染
  • 兼容 Element UI Tree:支持 Element UI Tree 的大部分 API
  • 可配置行高:支持自定义节点高度
  • 自适应模式:可切换为非虚拟滚动模式
  • 多种展开方式:支持默认展开、手动展开等

交互功能

  • 节点选择:支持单选、多选(checkbox)
  • 节点拖拽:支持节点拖拽排序和移动
  • 节点展开/折叠:支持点击展开、双击展开等
  • 节点过滤:支持根据关键词过滤节点
  • 高亮当前节点:支持高亮显示当前选中节点

性能优化

  • 按需渲染:只渲染可见区域内的节点
  • 回收复用:节点DOM元素会被回收复用
  • 缓冲机制:预渲染可见区域外的节点,提升滚动流畅度

安装

使用 npm 安装

npm install virtual-tree-component --save

使用 yarn 安装

yarn add virtual-tree-component

依赖

  • Vue.js:^2.6.14
  • vue-virtual-scroller:^1.1.2
  • Element UI:可选,组件样式基于 Element UI Tree

快速开始

全局引入

import Vue from 'vue'
import VirtualTree from 'virtual-tree-component'
import 'virtual-tree-component/assets/index.scss'

Vue.component('virtual-tree', VirtualTree)

局部引入

<template>
  <div class="app">
    <virtual-tree
      :data="treeData"
      :height="400"
      :item-size="26"
      @node-click="handleNodeClick"
    />
  </div>
</template>

<script>
import VirtualTree from 'virtual-tree-component'
import 'virtual-tree-component/assets/index.scss'

export default {
  components: {
    VirtualTree
  },
  data() {
    return {
      treeData: [
        {
          label: '一级 1',
          children: [
            {
              label: '二级 1-1',
              children: [
                {
                  label: '三级 1-1-1'
                }
              ]
            }
          ]
        },
        {
          label: '一级 2',
          children: [
            {
              label: '二级 2-1',
              children: [
                {
                  label: '三级 2-1-1'
                }
              ]
            },
            {
              label: '二级 2-2',
              children: [
                {
                  label: '三级 2-2-1'
                }
              ]
            }
          ]
        }
      ]
    }
  },
  methods: {
    handleNodeClick(data, node) {
      console.log('点击了节点:', data)
    }
  }
}
</script>

<style scoped>
.app {
  width: 400px;
  margin: 20px auto;
}
</style>

API

Props

| 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | 基础配置 | | | | | data | Array | [] | 树的数据源 | | height | [String, Number] | 0 | 树的高度,设置后启用虚拟滚动 | | item-size | Number | 26 | 每个节点的高度(单位:px) | | props | Object | { children: 'children', label: 'label', disabled: 'disabled' } | 配置树节点的属性 | | node-key | String | - | 每个树节点用来作为唯一标识的属性 | | 显示配置 | | | | | show-checkbox | Boolean | false | 是否显示复选框 | | highlight-current | Boolean | false | 是否高亮当前选中节点 | | indent | Number | 18 | 相邻级节点间的水平缩进,单位为像素 | | icon-class | String | - | 自定义树节点的图标 | | render-content | Function | - | 自定义节点内容 | | 交互配置 | | | | | expand-on-click-node | Boolean | true | 是否在点击节点的时候展开或者收缩节点 | | check-on-click-node | Boolean | false | 是否在点击节点的时候选中节点 | | auto-expand-parent | Boolean | true | 是否自动展开父节点 | | default-expand-all | Boolean | false | 是否默认展开所有节点 | | default-expanded-keys | Array | [] | 默认展开的节点的 key 的数组 | | default-checked-keys | Array | [] | 默认选中的节点的 key 的数组 | | current-node-key | [String, Number] | - | 当前选中的节点 | | check-strictly | Boolean | false | 在显示复选框的情况下,是否严格的遵循父子不互相关联的做法 | | check-descendants | Boolean | false | 当 check-strictly 为 false 时,是否自动检查子节点 | | draggable | Boolean | false | 是否开启拖拽功能 | | allow-drag | Function | - | 拖拽时判定节点是否可拖拽的函数 | | allow-drop | Function | - | 拖拽时判定目标节点能否被放置的函数 | | 性能配置 | | | | | render-after-expand | Boolean | true | 是否在第一次展开某个树节点后才渲染其子节点 | | lazy | Boolean | false | 是否懒加载子节点,需与 load 方法结合使用 | | load | Function | - | 加载子树数据的方法,仅当 lazy 属性为 true 时生效 | | keeps | Number | 40 | 虚拟滚动中保持的节点数量 | | extra-line | Number | 8 | 虚拟滚动中额外渲染的行数 | | 其他配置 | | | | | accordion | Boolean | false | 是否每次只打开一个同级树节点 | | filter-node-method | Function | - | 对树节点进行筛选时执行的方法 | | empty-text | String | '暂无数据' | 内容为空时的提示文本 |

Events

| 事件名称 | 回调参数 | 说明 | |----------|----------|------| | node-click | data, node, component | 节点被点击时触发 | | node-contextmenu | event, data, node, component | 节点被鼠标右键点击时触发 | | node-dblclick | data, node, component | 节点被双击时触发 | | node-expand | data, node, component | 节点被展开时触发 | | node-collapse | data, node, component | 节点被折叠时触发 | | node-check | data, checked, node | 节点复选框被点击时触发 | | check-change | data, checked, indeterminate | 节点选中状态发生变化时触发 | | current-change | data, node | 当前选中节点变化时触发 | | node-drag-start | node, event | 节点开始拖拽时触发 | | node-drag-enter | draggingNode, dropNode, dropType | 拖拽进入其他节点时触发 | | node-drag-leave | draggingNode, dropNode | 拖拽离开节点时触发 | | node-drag-over | draggingNode, dropNode, event | 拖拽经过节点时触发 | | node-drag-end | draggingNode, dropNode, dropType, event | 拖拽结束时触发 | | node-drop | draggingNode, dropNode, dropType, event | 拖拽成功完成时触发 |

Methods

| 方法名 | 参数 | 说明 | |--------|------|------| | filter | value | 对树节点进行筛选操作 | | updateKeyChildren | key, data | 通过 key 更新节点的子节点 | | append | data, parentNode | 为某个节点追加子节点 | | remove | data | 删除某个节点 | | insertBefore | data, refNode | 在参考节点前插入节点 | | insertAfter | data, refNode | 在参考节点后插入节点 | | getCheckedNodes | leafOnly, includeHalfChecked | 如果节点可被选择(show-checkbox 为 true),则返回当前选中的节点 | | getCheckedKeys | leafOnly | 如果节点可被选择(show-checkbox 为 true),则返回当前选中节点的 key 组成的数组 | | setCheckedNodes | nodes | 设置目前勾选的节点,使用此方法必须设置 node-key 属性 | | setCheckedKeys | keys, leafOnly | 通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性 | | setChecked | data, checked, deep | 设置节点是否选中,使用此方法必须设置 node-key 属性 | | getCurrentNode | - | 获取当前被选中的节点 | | setCurrentNode | node | 设置当前选中的节点,使用此方法必须设置 node-key 属性 | | getNode | data | 根据 data 或者 key 拿到对应的 node |

高级用法

虚拟滚动模式

通过设置 height 属性启用虚拟滚动:

<virtual-tree
  :data="treeData"
  :height="400px"
  :item-size="26"
  :default-expand-all="true"
/>

自定义节点内容

使用 render-content 属性自定义节点内容:

<virtual-tree
  :data="treeData"
  :height="400"
  :render-content="renderContent"
/>

<script>
export default {
  methods: {
    renderContent(h, { node, data, store }) {
      return (
        <div>
          <span>{data.label}</span>
          <button size="mini" onClick={() => this.handleEdit(data)}>
            编辑
          </button>
        </div>
      )
    },
    handleEdit(data) {
      console.log('编辑节点:', data)
    }
  }
}
</script>

拖拽功能

启用拖拽功能:

<virtual-tree
  :data="treeData"
  :height="400"
  :draggable="true"
  @node-drop="handleNodeDrop"
/>

<script>
export default {
  methods: {
    handleNodeDrop(draggingNode, dropNode, dropType) {
      console.log('拖拽完成:', draggingNode.data, dropNode.data, dropType)
    }
  }
}
</script>

懒加载

启用懒加载功能:

<virtual-tree
  :data="treeData"
  :height="400"
  :lazy="true"
  :load="loadNode"
  node-key="id"
/>

<script>
export default {
  methods: {
    loadNode(node, resolve) {
      if (node.level === 0) {
        return resolve([{ name: '一级节点', id: 1 }])
      }
      if (node.level > 2) {
        return resolve([])
      }
      // 模拟异步加载
      setTimeout(() => {
        const data = []
        for (let i = 1; i <= 10; i++) {
          data.push({
            name: `${node.data.name}-${i}`,
            id: `${node.data.id}-${i}`
          })
        }
        resolve(data)
      }, 500)
    }
  }
}
</script>

版本依赖要求

| Vue Version | Virtual Tree Version | vue-virtual-scroller Version | |-------------|----------------------|-------------------------------| | Vue 2.6.x | ^1.0.0 | ^1.1.2 | | Vue 2.7.x | ^1.0.0 | ^1.1.2 |

注意事项

  1. 虚拟滚动模式下

    • 必须设置 height 属性才能启用虚拟滚动
    • 建议设置固定的 item-size,确保滚动位置准确
    • 节点内容应保持固定高度,避免高度变化影响滚动
  2. 性能优化

    • 对于大数据量,建议使用 node-key 属性提高节点查找效率
    • 复杂节点内容建议使用 render-content 而非插槽
    • 启用 render-after-expand 可以减少初始渲染时间
  3. 兼容性

    • 兼容 Element UI Tree 的大部分 API,但某些高级功能可能有所不同
    • 支持现代浏览器,IE11 可能需要额外的 polyfill
  4. 样式问题

    • 组件样式基于 Element UI Tree,建议引入 Element UI 样式
    • 或根据需要自定义样式

许可证

MIT

贡献

欢迎提交 Issue 和 Pull Request!

更新日志

v1.0.0

  • 初始版本发布
  • 支持虚拟滚动
  • 兼容 Element UI Tree API
  • 支持拖拽、多选、懒加载等功能

常见问题

Q: 为什么设置了 height 属性但虚拟滚动不生效?

A: 请检查以下几点:

  • 确保 height 属性值大于 0
  • 确保数据已正确加载
  • 检查是否有样式冲突导致高度计算错误

Q: 为什么拖拽功能不工作?

A: 请检查:

  • 是否已设置 draggabletrue
  • 确保已设置 node-key 属性
  • 检查 allow-dragallow-drop 函数是否返回正确值

Q: 为什么节点内容显示异常?

A: 请检查:

  • render-content 函数是否正确返回 VNode
  • 节点数据的 label 属性是否存在
  • 样式是否有冲突

项目地址


感谢使用 Vue Virtual Tree Component!