我目前有一个TreeView组件,它包含一个tree。这个tree包含Children,每个Children都有一个label、perm和自己的children。
树的例子:
App.vue
let tree = ref({
label: 'org',
perm: {
POST: "auth",
GET: "null"
},
children: [
{
label: '*',
perm: {
POST: "auth",
GET: "null"
},
children: [{
label: 'repo',
perm: {
POST: "null",
GET: "null"
},
children: []
}]
},
{
label: 'test',
perm: {
POST: "auth",
GET: "auth"
},
children: []
}
]
})我目前在一个简单的树视图中使用以下方法显示这一点:
TreeView.vue
<div @click="toggleHideShow()">
{{ label }}
</div>
<div class="child" v-if="hideShow">
<TreeView v-for="child in children" :label="child.label" :perm="child.perm" :children="child.children" />
</div>我希望能够通过这个TreeView动态地添加子对象,那么有什么方法可以让我在点击时获得确切的Children对象呢?
现在,我尝试的是通过toggleHideShow方法传递属性:
<div @click="toggleHideShow(label, perm, children)"> 然后创建一个新的Children对象,循环遍历tree,然后比较每个对象以找到匹配的对象。
const toggleHideShow = (label: string, perm: Perm, children?: Array<Children>)=> {
hideShow.value = !hideShow.value
const newChild: Children = {
label: label,
perm: perm,
children: children
}
//do for loop here
}这里的问题是,我的tree变量是在我的项目的App.vue中声明的,我正在将这个tree对象传递到我的TreeView中。
<TreeView :label="tree.label" :perm="tree.perm" :children="tree.children" />所以我有三个问题:
1:如何从我的tree组件访问这个TreeView变量,并修改它,同时修改App.vue中的tree变量,从而动态更新TreeView
2:我最好在App.vue中声明一个方法,该方法接受新创建的newChild变量作为参数,然后从那里添加到树中?如果是这样的话,我将如何从我的TreeView组件创建这个方法?
他说:我还有其他方法来知道我点击的Children中的哪个tree对象吗?然后我如何从tree变量访问它,因为它不是一个数组?
发布于 2022-09-12 11:43:45
使用递归,对子节点所做的任何更改都必须在父级进行。如果您有2层深度,则发出更新父=>的事件,更新父=>更新父级=>更新子级的事件。
即使你有10层深,也会发生这种情况。
您可能会认为这种方法最大的问题是性能。事实并非如此。Vue在更改检测和渲染方面非常有效。
最大的问题将是调试。如果你开始在某种程度上发现错误,就很难找出哪里出了什么问题。
我建议一种更简单的方法:
identifiers
。
现在,每当您更新一个项目时,它的祖先和其后代都不需要知道更改的情况。
您可以拥有一个项目编辑器,该编辑器获取当前选定的项并对其进行修改。因为你不需要担心它的孩子们发生了什么,也不需要把这个变化广播到最高层,所以一切都是直接的和可测试的。
工作演示:https://codesandbox.io/s/editable-tree-bo6msx?file=/src/App.vue
为了使事情组织起来,我已经将与树相关的逻辑提取到一个存储中,它导出方法来添加/删除/编辑树项。
这种方法的另一个好处是,如果您需要,可以很容易地修改它以允许多个父级为同一项(唯一需要更改的是removeChild方法,它需要查找所有的父级,而不仅仅是一个)。
发布于 2022-09-12 02:40:49
最好的做法就是永远不要把道具的价值传给孩子。您应该从子节点发出返回到根节点(App.vue),并对树结构进行更改。考虑到数组和对象是通过引用传递的,所以可以发出当前TreeView节点的实际TreeView数组,然后App.vue可以推送到给定的数组,它实际上将在tree中更新适当的数组,而不必搜索它,这并不太复杂。
在下面的代码段中,我保持了hideShow在{{ label }}上的切换,但是添加了一个可以单击的新跨度,以在单击时添加一个子节点。它只是发射当前的children数组。所有TreeView节点都会捕捉到这个发出并再次传递它,直到到达App.vue为止,后者处理一个新的子节点的实际添加。
TreeView.vue
<template>
<li>
<div>
<span @click="hideShow = !hideShow">{{ label }}</span>
<span @click="$emit('addChild', children)">(add child)</span>
</div>
<div v-if="isOpen" class="child">
<ul>
<TreeView
v-for="(child, i) in children"
:key="i"
:label="child.label"
:perm="child.perm"
:children="child.children"
@add-child="$emit('addChild', $event)"
/>
</ul>
</div>
</li>App.vue
<template>
<ul>
<TreeView
:label="tree.label"
:perm="tree.perm"
:children="tree.children"
@add-child="addChild($event)"
/>
</ul>
</template>const addChild = item => {
item.push({
label: 'new item',
perm: {},
children: []
});
};您应该会发现,即使App接收到一个从发射端传递给它的数组,更新数组也会更新tree中相同的数组。
https://stackoverflow.com/questions/73649456
复制相似问题