# 图片预览
代码
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)