【问题标题】:Vue js data binding doesn't workVue js数据绑定不起作用
【发布时间】:2018-07-13 10:36:42
【问题描述】:

我正在尝试创建一个 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>

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    作为一个有趣的变体,您不需要克隆 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>

    【讨论】:

      【解决方案2】:

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

      您通过map 复制并将其分配给一个新数组这一事实掩盖了这一点,但它是对响应对象的引用数组,您已向每个对象添加了visible 属性。如果您检查父项中的数据项,您会发现它也添加了 visible

      最小的解决方法是使用Object.assign 创建一个新对象并将属性复制到其中。这样,所有属性都被插入到非响应对象中,然后在分配期间使其响应。

        mounted: function(){
          this.dataset = _.map(this.collection, function(element){
            return Object.assign({}, element, {visible: true});
          });
        },
      

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

      【讨论】:

        猜你喜欢
        • 2015-12-03
        • 2015-06-19
        • 1970-01-01
        • 1970-01-01
        • 2019-08-04
        • 2022-11-26
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        相关资源
        最近更新 更多