naive ui Tree 组件实现增删

naive ui Tree 组件实现增删

图片预览

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
<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
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)