I currently have a TreeView
component that contains a tree
. This tree
contains Children
that have each have a label
, perm
, and its own children
.
Example of the tree:
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: []
}
]
})
I'm currently displaying this in a simple Tree View using this:
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>
I intend to be able to add children dynamically through this TreeView, so is there a way for me to get the exact Children
object onclick?
Right now what I've tried is passing the attributes through the toggleHideShow
method:
<div @click="toggleHideShow(label, perm, children)">
and then creating a new Children
object, looping through the tree
and then comparing each one to find the matching object.
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
}
The problem here is that my tree
variable is declared in the App.vue of my project, and I am passing this tree
object into my TreeView
.
<TreeView :label="tree.label" :perm="tree.perm" :children="tree.children" />
So I have 3 questions:
1: How can I access this tree
variable from my TreeView
component, and would modifying it also modify the tree
variable that is inside my App.vue
, and hence dynamically updating the TreeView
?
2: Would it be better for me to declare a method inside App.vue
that took in the newly created newChild
variable as a parameter and then adding it to the tree from there? If so how would I go about creating this method from my TreeView
component?
3: Is there any other way for me to know which Children
object in the tree
I have clicked on? And then how would I access it from the tree
variable since it isn't an array?
With recursion, any change made to a child has to be made at parent level. If you're 2 levels deep, you emit an event updating the parent => emits an event upgrading the grand parent => updates the parent => updates the child.
This happens even when you're 10 levels deep.
You'd think the biggest problem with this approach is performance. It's not. Vue is quite efficient at change detection and rendering.
The biggest problem will be debugging. If you start getting errors at some level, it will be difficult to figure out where and what's wrong.
I suggest a simpler approach:
Now, whenever you update an item, neither its ancestors nor its descendants need to know about the change.
You can have an item editor which gets the currently selected item and can modify it. Because you don't need to worry about what happens to its children or about broadcasting the change to the top level, everything is more straight forward and testable.
Working demo: https://codesandbox.io/s/editable-tree-bo6msx?file=/src/App.vue
To keep things organised, I've extracted the tree related logic into a store, which exports methods to add/remove/edit tree items.
Another benefit of this approach is it could be easily modified to allow multiple parents for the same item, should you ever need it (the only thing that needs to change is removeChild
method, which needs to look for all parents, not for only one).