Vue js数据绑定不起作用

时间:2018-02-02 21:12:49

标签: javascript vue.js vuejs2 vue-component

我试图创建一个vue组件但是每当我想用v-show隐藏一些元素时,它都不起作用。

当你点击列表中的任何元素时我想要隐藏它,并且点击事件element.visible设置为false,所以在组件模板中我将该值绑定到v-show但它不会隐藏

我想这是因为element.visible它是一种嵌套属性,但我并不确定。



var collection = [
        { id: 1, name: 'element 1' },
        { id: 2, name: 'element 2' },
        { id: 3, name: 'element 3' },
        { id: 4, name: 'element 4' },
        { id: 5, name: 'element 5' },
        { id: 6, name: 'element 6' },
        { id: 7, name: 'element 7' },
        { id: 8, name: 'element 8' },
      ];

var multiselect = {
  props: ['collection'],
  data: function() {
    return {
      subscribed: [],
      toSubscribe: [],
      toUnsubscribe: [],
      dataset: []
    }
  },
  mounted: function(){
  	this.dataset = _.map(this.collection, function(element){
    	element.visible = true;
      return element;
    });
  },
  methods: {
    subscribe: function(element){
			element.visible = false;
    }
  }

}

new Vue({
  el: '#app',
  components: {
    'multiselect': multiselect
  },
  data: {
    elements: collection
  }
})

.multiselect .list {
  border: 1px solid #000;
  height: 215px;
  max-height: 215px;
  overflow: scroll;
}
.multiselect .list .list-element {
  text-align: center;
  padding: 0.2em;
  cursor: pointer;
}
.multiselect .list .list-element:hover {
  background-color: #d6dbdf;
}

<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.4/lodash.min.js"></script>
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>



<div id="app">

  <multiselect inline-template :collection="elements">
    <div class="col-sm-12 multiselect">

      <div class="col-sm-5 list">
        <div class="col-sm-12">
          <div v-for="element in dataset" class="list-element" @click="subscribe(element)" v-show="element.visible">
            {{element.name}}
          </div>
        </div>
      </div>

      <div class="col-sm-2">
        <button class="btn btn-primary btn-fill">
          <i class="fa fa-arrow-right" aria-hidden="true"></i>
        </button>

        <button class="btn btn-primary btn-fill">
          <i class="fa fa-arrow-left" aria-hidden="true"></i>
        </button>
      </div>

      <div class="col-sm-5 list">

      </div>

    </div>
  </multiselect>


</div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:2)

作为一个有趣的变体,您不需要克隆collection元素或在其上设置属性。

拥有一个并行的标志数组就足够了,但是你必须注意语法来更新它们,并且标志必须包含在一个对象中才能被观察到。
{ visible: true }的数组,而不是true的数组。

参考:Mutation-Methods

var collection = [
  { id: 1, name: 'element 1' },
  { id: 2, name: 'element 2' },
  { id: 3, name: 'element 3' },
  { id: 4, name: 'element 4' },
];

var multiselect = {
  props: ['collection'],
  data: function() {
    return {
      visibleFlags: []
    }
  },
  created: function(){
    this.collection.forEach(x => {
      this.visibleFlags.push({visible: true});  // Vue mutation method
    })
  },
  methods: {
    subscribe: function(index){
      this.$set(this.visibleFlags, index, false)
    }
  }
}

new Vue({
  el: '#app',
  components: {
    'multiselect': multiselect
  },
  data: {
    elements: collection
  }
})
.multiselect .list {
  border: 1px solid #000;
  height: 125px;
  max-height: 215px;
  overflow: scroll;
}
.multiselect .list .list-element {
  text-align: center;
  padding: 0.2em;
  cursor: pointer;
}
.multiselect .list .list-element:hover {
  background-color: #d6dbdf;
}
<script src="https://unpkg.com/vue@2.5.13/dist/vue.js"></script>
<div id="app">
  <multiselect inline-template :collection="elements">
    <div class="col-sm-12 multiselect">
      <div class="col-sm-5 list">
        <div class="col-sm-12">
          <div v-for="(element, index) in collection" 
            class="list-element" v-show="visibleFlags[index].visible" 
            @click="subscribe(index)">
            {{element.name}} 
          </div>
        </div>
      </div>
    </div>
  </multiselect>
</div>

答案 1 :(得分:1)

问题是您正在修改已经响应的对象。 Vue cannot detect property additions

您通过map进行复制并将其分配给新数组这一事实使其模糊不清,但它是对响应对象的引用数组,每个引用都添加了{{1}属性。如果您检查父级中的数据项,您会看到它也会添加visible

最小修复是使用visible创建新对象并将属性复制到其中。这样,所有属性都将插入到非响应对象中,然后在分配期间对其进行响应。

Object.assign

可以在创建中执行此操作,因为您不需要DOM元素。