@hjxz/pharos-tree
v0.0.1
Published
hjxz 树组件
Keywords
Readme
PharosTree 树组件
基于 Vue 3 和 Ant Design Vue 的树组件,支持无限级展开收起、拖拽、多选、联动等功能。
功能特性
- ✅ 可无限级展开收起子节点
- ✅ 可配置字符 fieldNames
- ✅ 树节点可以拖拽
- ✅ 支持静态数据和 API 请求两种数据导入方式
- ✅ 数据加载模式,加载中显示 Spinner 动画
- ✅ 可配置是否多选,支持全选、半选中、未选中状态
- ✅ 可配置联动规则,支持父子级节点是否联动
- ✅ 支持虚拟滚动,优化大量节点时的性能
安装
npm install @hjxz/pharos-tree
# 或
pnpm add @hjxz/pharos-tree基础用法
静态数据
<template>
<PharosTree :tree-data="treeData" />
</template>
<script setup lang="ts">
import { PharosTree } from '@hjxz/pharos-tree'
const treeData = [
{
key: '1',
label: '节点 1',
children: [
{
key: '1-1',
label: '节点 1-1',
children: [
{ key: '1-1-1', label: '节点 1-1-1' }
]
}
]
}
]
</script>API 数据
<template>
<PharosTree :api="fetchTreeData" />
</template>
<script setup lang="ts">
import { PharosTree } from '@hjxz/pharos-tree'
const fetchTreeData = async (params?: { parentId?: string }) => {
// 请求 API
const response = await fetch(`/api/tree?parentId=${params?.parentId || ''}`)
return response.json()
}
</script>配置 fieldNames
<template>
<PharosTree
:tree-data="treeData"
:field-names="{
key: 'id',
label: 'name',
children: 'childList'
}"
/>
</template>多选模式
<template>
<PharosTree
:tree-data="treeData"
checkable
:check-strictly="false"
v-model:checked-keys="checkedKeys"
@check="handleCheck"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const checkedKeys = ref<string[]>([])
const handleCheck = (keys: string[], info: any) => {
console.log('选中的节点:', keys)
console.log('半选中的节点:', info.halfCheckedKeys)
}
</script>拖拽功能
<template>
<PharosTree
:tree-data="treeData"
draggable
@dragstart="handleDragStart"
@drop="handleDrop"
/>
</template>
<script setup lang="ts">
const handleDragStart = (info: any) => {
console.log('开始拖拽:', info.node)
}
const handleDrop = (info: any) => {
console.log('放置节点:', info.node)
console.log('拖拽的节点:', info.dragNode)
// 在这里处理节点移动逻辑
}
</script>虚拟滚动
<template>
<PharosTree
:tree-data="treeData"
:virtual-scroll="true"
:visible-count="15"
:list-height="400"
:item-height="32"
/>
</template>
<script setup lang="ts">
import { PharosTree } from '@hjxz/pharos-tree'
// 虚拟滚动适用于节点数量较多的场景,可以显著提升性能
// visibleCount: 控制在视口中同时渲染的节点数量
// listHeight: 设置树容器的固定高度,超过此高度时显示滚动条
// itemHeight: 每个节点的高度,需要与实际节点高度一致
</script>API
Props
| 参数 | 说明 | 类型 | 默认值 |
|------|------|------|--------|
| treeData | 树形数据 | TreeNode[] | [] |
| api | 异步获取树数据的函数 | (params?: { parentId?: string }) => Promise<TreeNode[]> | - |
| indent | 缩进距离(px) | number | 16 |
| disabled | 是否禁用 | boolean | false |
| checkable | 是否显示复选框 | boolean | false |
| multiple | 是否多选 | boolean | false |
| fieldNames | 字段映射配置 | TreeFieldNames | - |
| draggable | 是否可拖拽 | boolean | false |
| checkStrictly | 是否启用父子节点关联。false 表示父子节点关联,true 表示不关联 | boolean | false |
| defaultExpandedKeys | 默认展开的节点 key | string[] | [] |
| defaultCheckedKeys | 默认选中的节点 key | string[] | [] |
| expandedKeys | 受控的展开节点 key(v-model:expandedKeys) | string[] | - |
| checkedKeys | 受控的选中节点 key(v-model:checkedKeys) | string[] | - |
| itemHeight | 节点高度(px) | number | 32 |
| noDataText | 无数据提示文本 | string | '暂无数据' |
| virtualScroll | 是否启用虚拟滚动 | boolean | false |
| visibleCount | 可见节点数量(仅在启用虚拟滚动时有效) | number | 10 |
| listHeight | 列表高度(px,仅在启用虚拟滚动时有效) | number | 256 |
Events
| 事件名 | 说明 | 回调参数 |
|--------|------|----------|
| update:checkedKeys | 选中节点变化时触发 | (keys: string[]) |
| update:expandedKeys | 展开节点变化时触发 | (keys: string[]) |
| check | 点击复选框时触发 | (keys: string[], info: { checked: boolean; node: TreeNodeInternal; checkedNodes: TreeNodeInternal[]; halfCheckedKeys?: string[] }) |
| expand | 展开/收起节点时触发 | (keys: string[], info: { expanded: boolean; node: TreeNodeInternal }) |
| select | 选择节点时触发(单选模式) | (keys: string[], info: { node: TreeNodeInternal; selected: boolean }) |
| dragstart | 开始拖拽时触发 | (info: { event: DragEvent; node: TreeNodeInternal }) |
| dragenter | 拖拽进入节点时触发 | (info: { event: DragEvent; node: TreeNodeInternal; expanded: boolean }) |
| dragover | 拖拽悬停在节点上时触发 | (info: { event: DragEvent; node: TreeNodeInternal }) |
| dragleave | 拖拽离开节点时触发 | (info: { event: DragEvent; node: TreeNodeInternal }) |
| drop | 放置节点时触发 | (info: { event: DragEvent; node: TreeNodeInternal; dragNode: TreeNodeInternal }) |
| dragend | 拖拽结束时触发 | (info: { event: DragEvent; node: TreeNodeInternal }) |
| load | 节点懒加载完成时触发 | (node: TreeNodeInternal) |
TreeFieldNames
| 字段 | 说明 | 类型 | 默认值 |
|------|------|------|--------|
| key | 唯一标识字段名 | string | 'key' |
| label | 显示文本字段名 | string | 'label' |
| value | 值字段名 | string | 'key' |
| children | 子节点字段名 | string | 'children' |
| disabled | 禁用状态字段名 | string | 'disabled' |
| isLeaf | 是否叶子节点字段名 | string | 'isLeaf' |
| extra | 额外数据字段名 | string | 'extra' |
TreeNode
| 字段 | 说明 | 类型 | 必填 |
|------|------|------|------|
| key | 唯一标识 | string | ✅ |
| label | 显示文本 | string | ✅ |
| children | 子节点 | TreeNode[] | - |
| disabled | 是否禁用 | boolean | - |
| isLeaf | 是否叶子节点 | boolean | - |
| value | 值 | string | - |
| extra | 额外数据 | any | - |
示例
完整示例
<template>
<div>
<PharosTree
:tree-data="treeData"
:field-names="fieldNames"
checkable
:check-strictly="false"
draggable
:virtual-scroll="true"
:visible-count="15"
:list-height="400"
:default-expanded-keys="['1']"
:default-checked-keys="['1-1']"
v-model:checked-keys="checkedKeys"
v-model:expanded-keys="expandedKeys"
@check="handleCheck"
@expand="handleExpand"
@drop="handleDrop"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { PharosTree } from '@hjxz/pharos-tree'
const treeData = [
{
key: '1',
label: '父节点 1',
children: [
{ key: '1-1', label: '子节点 1-1' },
{ key: '1-2', label: '子节点 1-2' }
]
},
{
key: '2',
label: '父节点 2',
children: [
{ key: '2-1', label: '子节点 2-1' },
{ key: '2-2', label: '子节点 2-2' }
]
}
]
const fieldNames = {
key: 'key',
label: 'label',
children: 'children'
}
const checkedKeys = ref<string[]>([])
const expandedKeys = ref<string[]>([])
const handleCheck = (keys: string[], info: any) => {
console.log('选中的节点:', keys)
console.log('半选中的节点:', info.halfCheckedKeys)
}
const handleExpand = (keys: string[], info: any) => {
console.log('展开的节点:', keys)
}
const handleDrop = (info: any) => {
console.log('放置节点:', info.node)
console.log('拖拽的节点:', info.dragNode)
}
</script>注意事项
- 当使用 API 方式加载数据时,组件会在节点展开时自动调用 API 加载子节点(懒加载)
- 拖拽功能中,不允许将节点拖拽到自己的子节点中
- 半选中状态只在
checkStrictly: false(父子节点关联)时生效 - 当
checkStrictly: true时,父子节点的选中状态互不影响 - 虚拟滚动:
- 当节点数量较多(建议超过 100 个可见节点)时,建议启用虚拟滚动以提升性能
itemHeight需要与实际节点高度一致,否则可能出现滚动位置不准确的问题visibleCount建议设置为略大于可视区域内能显示的节点数量,一般设置为Math.ceil(listHeight / itemHeight) + 2- 虚拟滚动模式下,只渲染可见区域的节点,滚动时会动态加载和卸载节点
- 虚拟滚动与拖拽功能完全兼容,可以同时使用
License
MIT
