# 图片预览

image-20230518225145921

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<template>
<n-tree
block-line
:data="treeData"
:selectable="false"
:default-expand-all="true"
/>
</template>

<script lang="ts" setup>
import { h, ref } from 'vue'
import { TreeOption, NButton, NTree } from 'naive-ui'

function getUuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (c) {
const r = (Math.random() * 16) | 0,
v = c == 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
}
)
}

const onCreateBtn = (childrenData: TreeOption[]) => {
console.log(childrenData)
const key = getUuid()
childrenData.push(createTreeOption(getUuid(), '新增' + key, childrenData))
const newData = [...treeData.value]
treeData.value = newData
console.log(childrenData)
}

const onDelete = (key: string, parentData?: TreeOption[]) => {
if (!parentData) return
console.log(parentData)
console.log(key)
const index = parentData.findIndex((item) => item.key === key)
console.log(index)
if (index !== -1) {
parentData.splice(index, 1)
const newData = [...treeData.value]
treeData.value = newData
}
}

const createTreeOption = (
key: string,
label: string,
parentData?: TreeOption[]
): TreeOption => {
const children: TreeOption[] = []
return {
label,
key,
children,
suffix: () => {
return h('div', {}, [
h(
NButton,
{
text: true,
type: 'primary',
attrs: {
dataId: key
},
onClick: () => onCreateBtn(children)
},
{
default: () => '新增'
}
),
h(
NButton,
{
text: true,
type: 'error',
attrs: {
dataId: key
},
style: 'marginLeft: 10px;',
onClick: () => onDelete(key, parentData)
},
{
default: () => '删除'
}
)
])
}
}
}

const createRoot = () => {
const root = createTreeOption('root', '根节点')
return root
}

const treeData = ref<TreeOption[]>([createRoot()])
</script>

缺点

每次都新创建了一个新的 data 用的渲染。 没看Tree 组件的源码, 不知道会不会走 Vue 的 diff 阶段。

优化点, 可以使用 Tree 组件自带的onLoad 方法处理父节点的 children。

这里有个疑问,怎官网里onLoad例子里面, 也是直接改变的 children。 但是你用 reactive包裹treeData,然后去改变父节点的 children,会发现无法更新。 所以我的代码里面用的ref.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
handleLoad (node: TreeOption) {
return new Promise<void>((resolve) => {
setTimeout(() => {
node.children = [
{
label: nextLabel(node.label),
key: node.key + nextLabel(node.label),
isLeaf: false
}
]
resolve()
}, 1000)
})
}

有个 issue 可能会在未来添加这种需求的解决办法Tree组件新增getNode、remove、append、insertBefore、insertAfter方法 · Issue #4591 · tusen-ai/naive-ui (github.com)