使用 VueJS 嵌套输入的树视图
Treeview with nested inputs with VueJS
我正在尝试构建一个包含输入的树视图组件以更改我的源 json。
绑定部分似乎工作正常,但分支上的 hide/show 操作已损坏:
HTML :
<div id="app">
<tree :data="json" :link="json"></tree>
<p>Outside component :</p>
<pre>{{json}}</pre>
</div>
JS :
let json = {
nodeA: {
nodeA1 : "valueA1",
nodeA2 : "valueA2"
},
nodeB: "valueB",
nodeC: {
nodeC1 : "valueC1",
nodeC2 : "valueC2"
}
};
Vue.component('tree', {
name: 'treeview',
props: [
'data',
'link'
],
template: `<ul>
<li v-for="(val, key) in data">
<input type="text" v-if="isLeaf(val)" v-model=link[key]>
<span @click="toggle">{{key}}</span>
<tree v-if="!isLeaf(val)" v-show="show" :data="val" :link="link[key]">
</tree>
</li>
</ul>`,
data: function() {
return {
show: false
};
},
methods: {
isLeaf: function(node) {
return typeof node != 'object';
},
toggle: function() {
this.show = !this.show;
}
}
});
new Vue({
el: '#app',
data: {
json: json
}
});
https://codepen.io/anon/pen/EZKBwL
如您所见,单击第一个分支 ("nodeA") 会同时激活第一个和第三个分支...
我认为问题出在父组件上发生的点击,但我找不到修复代码的方法。
这是因为您将所有元素绑定到同一个参数。
要单独切换每个元素的可见性,您需要将元素状态存储在它自己的位置,例如对象的字段或数组。
但我想更好的解决方案是通过单击在目标元素上切换 class 并通过 css 通过 class 控制可见性。
您的所有分支都 hiding/showing 在一起,因为您使用单个变量 show
来隐藏和显示这两个分支,您必须为每个节点使用不同的变量。
拥有与节点数量一样多的变量是不切实际的,但您可以拥有如下所示的散列:
data: function() {
return {
show: {}
};
},
并更改切换方法,通过在该 show
散列中为该节点创建一个键来为每个节点设置变量。您可以为此使用 vm.$set,其中 在对象上设置 属性。如果对象是反应性的,确保 属性 创建为反应性 属性 并触发视图更新。
toggle: function(node) {
if(this.show[node]){
this.$set(this.show, node, false)
} else {
this.$set(this.show, node, true)
}
}
你也需要在HTML中做相应的修改,可以在working codepen中查看here。
您可能需要每个节点的 show
字段来分别切换它们的可见性,在我的 improved example 中,我使用的是这样的数据结构:
{
"nodeA": {
"value": {
"nodeA1": {
"value": "valueA1",
"show": false
},
"nodeA2": {
"value": "valueA2",
"show": false
}
},
"show": true
},
"nodeB": {
"value": "valueB",
"show": true
}
}
我的模板:
<ul>
<li v-for="(val, key) in data" v-show='val.show'>
<input type="text" v-if="isLeaf(val)" v-model='link[key].value'>
<span @click="toggle(val.value)">{{key}}</span>
<tree v-if="!isLeaf(val)" :data="val.value" :link="val.value">
</tree>
</li>
</ul>
方法:
{
isLeaf: function(node) {
return typeof node.value != 'object';
},
toggle: function(value) {
for (const nodeName in value) {
value[nodeName].show = !value[nodeName].show;
}
}
}
我正在尝试构建一个包含输入的树视图组件以更改我的源 json。
绑定部分似乎工作正常,但分支上的 hide/show 操作已损坏:
HTML :
<div id="app">
<tree :data="json" :link="json"></tree>
<p>Outside component :</p>
<pre>{{json}}</pre>
</div>
JS :
let json = {
nodeA: {
nodeA1 : "valueA1",
nodeA2 : "valueA2"
},
nodeB: "valueB",
nodeC: {
nodeC1 : "valueC1",
nodeC2 : "valueC2"
}
};
Vue.component('tree', {
name: 'treeview',
props: [
'data',
'link'
],
template: `<ul>
<li v-for="(val, key) in data">
<input type="text" v-if="isLeaf(val)" v-model=link[key]>
<span @click="toggle">{{key}}</span>
<tree v-if="!isLeaf(val)" v-show="show" :data="val" :link="link[key]">
</tree>
</li>
</ul>`,
data: function() {
return {
show: false
};
},
methods: {
isLeaf: function(node) {
return typeof node != 'object';
},
toggle: function() {
this.show = !this.show;
}
}
});
new Vue({
el: '#app',
data: {
json: json
}
});
https://codepen.io/anon/pen/EZKBwL
如您所见,单击第一个分支 ("nodeA") 会同时激活第一个和第三个分支...
我认为问题出在父组件上发生的点击,但我找不到修复代码的方法。
这是因为您将所有元素绑定到同一个参数。
要单独切换每个元素的可见性,您需要将元素状态存储在它自己的位置,例如对象的字段或数组。
但我想更好的解决方案是通过单击在目标元素上切换 class 并通过 css 通过 class 控制可见性。
您的所有分支都 hiding/showing 在一起,因为您使用单个变量 show
来隐藏和显示这两个分支,您必须为每个节点使用不同的变量。
拥有与节点数量一样多的变量是不切实际的,但您可以拥有如下所示的散列:
data: function() {
return {
show: {}
};
},
并更改切换方法,通过在该 show
散列中为该节点创建一个键来为每个节点设置变量。您可以为此使用 vm.$set,其中 在对象上设置 属性。如果对象是反应性的,确保 属性 创建为反应性 属性 并触发视图更新。
toggle: function(node) {
if(this.show[node]){
this.$set(this.show, node, false)
} else {
this.$set(this.show, node, true)
}
}
你也需要在HTML中做相应的修改,可以在working codepen中查看here。
您可能需要每个节点的 show
字段来分别切换它们的可见性,在我的 improved example 中,我使用的是这样的数据结构:
{
"nodeA": {
"value": {
"nodeA1": {
"value": "valueA1",
"show": false
},
"nodeA2": {
"value": "valueA2",
"show": false
}
},
"show": true
},
"nodeB": {
"value": "valueB",
"show": true
}
}
我的模板:
<ul>
<li v-for="(val, key) in data" v-show='val.show'>
<input type="text" v-if="isLeaf(val)" v-model='link[key].value'>
<span @click="toggle(val.value)">{{key}}</span>
<tree v-if="!isLeaf(val)" :data="val.value" :link="val.value">
</tree>
</li>
</ul>
方法:
{
isLeaf: function(node) {
return typeof node.value != 'object';
},
toggle: function(value) {
for (const nodeName in value) {
value[nodeName].show = !value[nodeName].show;
}
}
}