更新 VueJS 中递归树视图的初始数组
Update the inital array of a recursive treeview in VueJS
我正在学习 this 我自己的树视图教程,其中包含 vuejs 中的递归组件。
所以输入数组看起来像这样:
let tree = {
label: 'root',
nodes: [
{
label: 'item1',
nodes: [
{
label: 'item1.1'
},
{
label: 'item1.2',
nodes: [
{
label: 'item1.2.1'
}
]
}
]
},
{
label: 'item2'
}
]
}
<template>
<div>
...
<tree-menu
v-for="node in nodes"
:nodes="node.nodes"
:label="node.label" />
...
</div>
<template
<script>
export default {
props: [ 'label', 'nodes' ],
name: 'tree-menu'
}
</script>
所以基本上一个标签和一个节点子数组被传递给一个子节点。现在我想更新或删除一个节点(例如 item1.1),但在最外层数组(此处 tree
)中反映此更改,因为我想将此更新的结构发送到服务器。我怎样才能做到这一点?如果我更改节点的标签,这将在 DOM 中呈现,但 tree
数组不会更新。
以下是使用 .sync
修饰符递归更新的方法:
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('tree-node', {
template: `
<div style="margin-left: 5px;">
<input :value="label"
type="text"
@input="$emit('update:label', $event.target.value)" />
<tree-node v-for="(node, key) in nodes"
:key="key"
v-bind.sync="node" />
</div>
`,
props: ['label', 'nodes']
});
let tree = {
label: 'root',
nodes: [{
label: 'item 1',
nodes: [
{ label: 'item 1.1' },
{ label: 'item 1.2',
nodes: [
{ label: 'item 1.2.1' }
]
}
]
},
{ label: 'item 2' }
]
};
new Vue({
el: '#app',
data: () => ({
tree
})
})
#app {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<div id="app">
<div>
<tree-node v-bind.sync="tree" />
</div>
<pre v-html="tree" />
</div>
对于 :label.sync="node.label" :nodes.sync="node.nodes"
,v-bind.sync="node"
是 shorthand。 v-bind
将所有对象成员解包为标签的属性,从而为组件生成 props。
解决方案的另一半是将输入中的 v-model
替换为 :value
+ 对 @input
的 $emit('update:propName', $event.target.value)
调用更新了 .sync
-在父级中编辑 属性。为了概念化它,它是 Vue 公开的 DIY v-model
,因此可以对其进行自定义(您决定何时调用更新以及更新什么)。您可以将 <input>
替换为任何其他类型的输入,具体取决于您的 binding/modifying(复选框、文本区域、select 或您的框架可能具有的任何更高级的输入包装器)。根据输入类型,您需要自定义侦听器:@change
、@someCustomEvent
等...
.sync
使每个级别的一切都具有反应性。因为一切都是 :key
-ed,实际上没有重新渲染发生(Vue 只重新渲染实际改变的 DOM 元素)。如果不是这种情况,输入将在重新渲染时失去焦点。
更新原则是:更新父 属性 而不是在子级别进行更改,父 属性 通过 v-bind
将其发回给子。
这与 Vuex 使用的原理完全相同。与其更改某些本地属性,不如调用存储突变,它通过 getter 返回并修改本地值,但它发生在使用该存储数据的任何组件上,而不仅仅是当前组件。
我正在学习 this 我自己的树视图教程,其中包含 vuejs 中的递归组件。 所以输入数组看起来像这样:
let tree = {
label: 'root',
nodes: [
{
label: 'item1',
nodes: [
{
label: 'item1.1'
},
{
label: 'item1.2',
nodes: [
{
label: 'item1.2.1'
}
]
}
]
},
{
label: 'item2'
}
]
}
<template>
<div>
...
<tree-menu
v-for="node in nodes"
:nodes="node.nodes"
:label="node.label" />
...
</div>
<template
<script>
export default {
props: [ 'label', 'nodes' ],
name: 'tree-menu'
}
</script>
所以基本上一个标签和一个节点子数组被传递给一个子节点。现在我想更新或删除一个节点(例如 item1.1),但在最外层数组(此处 tree
)中反映此更改,因为我想将此更新的结构发送到服务器。我怎样才能做到这一点?如果我更改节点的标签,这将在 DOM 中呈现,但 tree
数组不会更新。
以下是使用 .sync
修饰符递归更新的方法:
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('tree-node', {
template: `
<div style="margin-left: 5px;">
<input :value="label"
type="text"
@input="$emit('update:label', $event.target.value)" />
<tree-node v-for="(node, key) in nodes"
:key="key"
v-bind.sync="node" />
</div>
`,
props: ['label', 'nodes']
});
let tree = {
label: 'root',
nodes: [{
label: 'item 1',
nodes: [
{ label: 'item 1.1' },
{ label: 'item 1.2',
nodes: [
{ label: 'item 1.2.1' }
]
}
]
},
{ label: 'item 2' }
]
};
new Vue({
el: '#app',
data: () => ({
tree
})
})
#app {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.js"></script>
<div id="app">
<div>
<tree-node v-bind.sync="tree" />
</div>
<pre v-html="tree" />
</div>
:label.sync="node.label" :nodes.sync="node.nodes"
,v-bind.sync="node"
是 shorthand。 v-bind
将所有对象成员解包为标签的属性,从而为组件生成 props。
解决方案的另一半是将输入中的 v-model
替换为 :value
+ 对 @input
的 $emit('update:propName', $event.target.value)
调用更新了 .sync
-在父级中编辑 属性。为了概念化它,它是 Vue 公开的 DIY v-model
,因此可以对其进行自定义(您决定何时调用更新以及更新什么)。您可以将 <input>
替换为任何其他类型的输入,具体取决于您的 binding/modifying(复选框、文本区域、select 或您的框架可能具有的任何更高级的输入包装器)。根据输入类型,您需要自定义侦听器:@change
、@someCustomEvent
等...
.sync
使每个级别的一切都具有反应性。因为一切都是 :key
-ed,实际上没有重新渲染发生(Vue 只重新渲染实际改变的 DOM 元素)。如果不是这种情况,输入将在重新渲染时失去焦点。
更新原则是:更新父 属性 而不是在子级别进行更改,父 属性 通过 v-bind
将其发回给子。
这与 Vuex 使用的原理完全相同。与其更改某些本地属性,不如调用存储突变,它通过 getter 返回并修改本地值,但它发生在使用该存储数据的任何组件上,而不仅仅是当前组件。