首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Vue 3树视图中将对象添加到另一个对象

如何在Vue 3树视图中将对象添加到另一个对象
EN

Stack Overflow用户
提问于 2022-09-08 12:56:31
回答 2查看 91关注 0票数 0

我目前有一个TreeView组件,它包含一个tree。这个tree包含Children,每个Children都有一个labelperm和自己的children

树的例子:

App.vue

代码语言:javascript
复制
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

代码语言:javascript
复制
 <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方法传递属性:

代码语言:javascript
复制
 <div @click="toggleHideShow(label, perm, children)"> 

然后创建一个新的Children对象,循环遍历tree,然后比较每个对象以找到匹配的对象。

代码语言:javascript
复制
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中。

代码语言:javascript
复制
<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变量访问它,因为它不是一个数组?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-09-12 11:43:45

使用递归,对子节点所做的任何更改都必须在父级进行。如果您有2层深度,则发出更新父=>的事件,更新父=>更新父级=>更新子级的事件。

即使你有10层深,也会发生这种情况。

您可能会认为这种方法最大的问题是性能。事实并非如此。Vue在更改检测和渲染方面非常有效。

最大的问题将是调试。如果你开始在某种程度上发现错误,就很难找出哪里出了什么问题。

我建议一种更简单的方法:

identifiers

  • instead

  • 将您的所有项目放入一个平面数组中,并为它们提供唯一的将项保存在子级内的

  • ,只保留它们的ids

现在,每当您更新一个项目时,它的祖先和其后代都不需要知道更改的情况。

您可以拥有一个项目编辑器,该编辑器获取当前选定的项并对其进行修改。因为你不需要担心它的孩子们发生了什么,也不需要把这个变化广播到最高层,所以一切都是直接的和可测试的。

工作演示:https://codesandbox.io/s/editable-tree-bo6msx?file=/src/App.vue

为了使事情组织起来,我已经将与树相关的逻辑提取到一个存储中,它导出方法来添加/删除/编辑树项。

这种方法的另一个好处是,如果您需要,可以很容易地修改它以允许多个父级为同一项(唯一需要更改的是removeChild方法,它需要查找所有的父级,而不仅仅是一个)。

票数 1
EN

Stack Overflow用户

发布于 2022-09-12 02:40:49

最好的做法就是永远不要把道具的价值传给孩子。您应该从子节点发出返回到根节点(App.vue),并对树结构进行更改。考虑到数组和对象是通过引用传递的,所以可以发出当前TreeView节点的实际TreeView数组,然后App.vue可以推送到给定的数组,它实际上将在tree中更新适当的数组,而不必搜索它,这并不太复杂。

在下面的代码段中,我保持了hideShow在{{ label }}上的切换,但是添加了一个可以单击的新跨度,以在单击时添加一个子节点。它只是发射当前的children数组。所有TreeView节点都会捕捉到这个发出并再次传递它,直到到达App.vue为止,后者处理一个新的子节点的实际添加。

TreeView.vue

代码语言:javascript
复制
<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

代码语言:javascript
复制
<template>
  <ul>
    <TreeView
      :label="tree.label"
      :perm="tree.perm"
      :children="tree.children"
      @add-child="addChild($event)"
    />
  </ul>
</template>
代码语言:javascript
复制
const addChild = item => {
  item.push({
    label: 'new item',
    perm: {},
    children: []
  });
};

您应该会发现,即使App接收到一个从发射端传递给它的数组,更新数组也会更新tree中相同的数组。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73649456

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档