使用VueJS嵌套输入的Treeview

时间:2017-01-12 22:52:53

标签: javascript vue-component vuejs2 vue.js

我正在尝试构建一个使用输入的树视图组件来更改我的源json。

绑定部分似乎工作正常,但分支上的隐藏/显示操作被破坏:

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

如您所见,点击第一个分支(&#34; nodeA&#34;)激活第一个和第三个分支......

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

3 个答案:

答案 0 :(得分:0)

之所以发生这种情况,是因为您将所有元素绑定在同一个参数上。

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

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

答案 1 :(得分:0)

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

拥有与节点数一样多的变量是不切实际的,但是你可以有如下的散列:

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

并更改toggle方法,通过在该节点的此show哈希中创建一个键来为每个节点设置变量。您可以使用vm.$set来为设置对象的属性。如果对象是被动的,请确保将该属性创建为被动属性并触发视图更新。

toggle: function(node) {
  if(this.show[node]){
    this.$set(this.show, node, false)
  } else {
    this.$set(this.show, node, true)
  }
} 

您还需要对HTML进行相应的更改,这可以在工作代码集here中查看。

答案 2 :(得分:-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;
        }
    }
}