绑定到对象的Vue.js类在对象更新时不会更改

时间:2019-06-21 07:30:12

标签: javascript vue.js

我有许多按钮,是通过v-for指令生成的。它们都基于对象的字符串具有初始类。我有一个事件,那就是单击按钮时更改此字符串。但是该类没有被更新。我在做什么错了?

<template>
    <v-layout>
        <v-btn v-for="cell in cells" :key='cell.id' v-bind:class='cell.color' 
            v-on:click='click(cell.id)'>
            <p v-if="cell.win">win</p>
            <p>{{cell.id}}</p>
        </v-btn>
    </v-layout>
</template>

<script>

export default {
    data: () => {
        return {
            cells: {

            },
            winId: 0,
        }
    },
    methods: {
        generateCells() {
            this.winId = Math.floor(Math.random() * 100);
            for (var i = 0; i < 100; i++) {
                this.cells[i] = {
                    id: i,
                    color: 'info'
                }
            }
        },
        click(id) {
            if (this.cells[id] == this.winId) {
                alert('you win');
                this.cells[id].color = 'success';
            } else {
                this.cells[id].color = 'warning';
            }
        }
    },
    created() {
        this.generateCells();
    }
}

</script>

我希望按钮类可以在对象更新后更新。对象.color prperty已更新,但该类保持初始状态。

2 个答案:

答案 0 :(得分:1)

  

由于现代JavaScript的局限性(以及Object.observe的放弃),Vue无法检测到属性的添加或删除。由于Vue在实例初始化期间执行getter / setter转换过程,因此,数据对象中必须存在一个属性,以便Vue对其进行转换并使其具有反应性。

在此处了解更多信息:Reactivity in Depth

Vue提供了一个API,可以向嵌套的关卡对象添加属性并使它们具有反应性。

为此,您可以使用

Vue.set(object, propertyName, value);

您还可以使用vm.$set方法

this.$set(this.someObject, 'b', 2);

因此,在您的代码中,您需要在其中设置数组的值

this.$set(this.cells, i, {
                           id: i,
                           color: 'info'
                         });

请参阅下面的完整代码段:

window.onload = () => {
  new Vue({
    el: '#app',
    data: () => {
      return {
        cells: {

        },
        winId: 0,
      }
    },
    methods: {
      generateCells() {
        this.winId = Math.floor(Math.random() * 100);
        for (var i = 0; i < 100; i++) {
          this.$set(this.cells, i, {
            id: i,
            color: 'info'
          })
        }
      },
      click(id) {
        if (this.cells[id] == this.winId) {
          alert('you win');
          this.cells[id].color = 'success';
        } else {
          this.cells[id].color = 'warning';
        }
      }
    },
    created() {
      this.generateCells();
    }
  })
}
body {
  padding: 1rem;
}

.info {
  color: blue;
}

.warning {
  color: red;
}

.success {
  color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <v-layout>
    <v-btn v-for="cell in cells" :key='cell.id' v-bind:class='cell.color' v-on:click='click(cell.id)'>
      <p v-if="cell.win">win</p>
      <p>{{cell.id}}</p>
    </v-btn>
  </v-layout>
</div>

答案 1 :(得分:0)

详细了解Vue documentation中的数据和方法。

  

应该注意的是,数据中的属性只有在它们具有属性时才是反应性的   创建实例时存在。这意味着如果您添加新   属性,例如:

vm.b = 'hi'
     

对b的更改不会触发任何视图更新。

在循环中设置prop值时,可以使用Vue.set()this.$set() API。

或替换整个对象,例如:

var cells = {}
for (var i = 0; i < 100; i++) {
    cells[i] = {
    id: i,
    color: 'info'
    }
}
this.cells = cells

然后在点击回调中:

var newCell = {}
if (this.cells[id] == this.winId) {
    alert('you win');
    newCell[id] = {id:id,color:'success'}
} else {
    newCell[id] = {id:id,color:'warning'}
}
this.cells = Object.assign({},this.cells,newCell)