首页 文章

Vue js数据绑定不起作用

提问于
浏览
1

我正在尝试创建一个vue组件,但每当我想用 v-show 隐藏一些元素时它就不起作用了 .

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

我想这是因为 element.visible 它's kind of nested attribute but I'我不太确定 .

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>

2 回答

  • 1

    问题是您正在修改已经响应的对象 . 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});
        });
      },
    

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

  • 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>
    

相关问题