Vue js数据绑定不起作用

Posted

技术标签:

【中文标题】Vue js数据绑定不起作用【英文标题】:Vue js data binding doesn't work 【发布时间】: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>

【问题讨论】:

【参考方案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 元素。

【讨论】:

以上是关于Vue js数据绑定不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Vue.js - 选择/下拉选定项 vm 绑定不起作用(bootstrap-vue)

Vue js遍历数据子属性不起作用

vue双向绑定时添加.sync不起作用的原因

Vue动态绑定到类不起作用

Vue JS CSS 样式绑定

Vue.js 和 jQuery datepicker/timepicker 双向绑定