2017-01-12 114 views
1

我想构建一个树视图组件comporting输入以改变我的源json。树视图嵌套输入与VueJS

结合部似乎很好地工作,但在树枝隐藏/显示动作被打破:

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”)激活这两个第一个和第三个分支...

我认为问题来自父组件上发生的点击,但我找不到修复我的代码的方法。

回答

0

当您使用单个变量show来隐藏和显示这两者时,您的所有分支一起隐藏/显示,您必须为每个节点使用不同的变量。

这将是不切实际的,有尽可能多的变量节点的数量,但你可以有一个像下面的哈希:

data: function() { 
    return { 
     show: {} 
    }; 
    }, 

,改变切换方法,通过创建密钥设置每个节点的变量在该节点的这个show散列中。您可以使用vm.$set来为此设置对象的属性。如果对象处于被动状态,请确保将该属性创建为反应属性并触发视图更新。

你需要做的HTML相应的变化,以及,它可以在工作codepen here观看。

+0

简单但高效:)另外,是th使用源JSON绑定嵌套输入的一个更好的解决方案,而不是将链接作为通道传递? – Pourpre

+0

@Pourpre如果你问道具的替代品,你可以使用vuex如果它适合你的要求,你可以看[文档](https://vuex.vuejs.org/en/)或我的回答[这里]( HTTP://计算器。com/a/40830610/1610034)或[here](http://stackoverflow.com/questions/40953496/vue-shared-data-between-different-pages/40955110#40955110)。 – Saurabh

0

发生这种情况是因为您将所有元素绑定在相同的参数上。

要为每个元素单独切换可见性,您需要将元素状态存储在自己的位置,如对象的字段或数组。

但我想更好的解决方案是切换目标元素上的类通过单击和通过类的css控制可见性。

-1

您可能需要一个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; 
     } 
    } 
} 
+1

此解决方案是功能性的,但需要对源JSON进行重大更改,这是不需要的。感谢您的提议。 – Pourpre