如何在v-for呈现的对象中发生更改时更新DOM?

时间:2017-05-01 15:34:37

标签: vue.js vuejs2 vue-component v-for

我正在使用v-for根据对象数组呈现列表。

<ul>
  <li v-for="category, i in categories"
  :class="{active: category.active}"
  @click="changeCategory(i)">
    <a>{{ category.service_type_name }}</a>
  </li>
</ul>

单击列表项changeCategory(index)时运行:

changeCategory(index) {
    this.categories.forEach((c, i) => {
        c.active = (i != index)? false : true
    })
}

因此,点击列表项active属性设置为true,其他所有属性设置为false,列表项会添加.active类(因为模板中的:class="{active: category.active}"行。

但是,DOM未更新以显示此更改。

在发生此更改时,是否仍然自动更新DOM,而不使用this.$forceUpdate()函数中的changeCategory(index)

编辑:将map更改为forEach,DOM仍未更新。

编辑:我正在使用带有typescript

的vue-class-components
import Vue from 'app/vueExt'
import { Component } from 'vue-property-decorator'
import * as Template from './services.vue'

@Component({
    mixins: [Template]
})
export default class Services extends Vue {
    categories = []

    created() {
        this.api.getServiceSetupCatagories().then((res) => {
            this.categories = res.categories
            this.categories.forEach((c, i) => {
                // adding active property to the object
                // active = true if i = 0, false otherwise
                c.active = (i)? false : true
            })
        })
    }

    changeCategory(index) {
        this.categories.forEach((c, i) => {
            c.active = (i != index)? false : true
        })
    }
}

2 个答案:

答案 0 :(得分:2)

在讨论了这个问题后,我提出了以下替代方法。

activeIndex添加到data并将模板更改为以下内容。

<ul>
  <li v-for="category, i in categories"
      :class="{active: activeIndex === i}"
      @click="activeIndex = i">
    <a>{{ category.service_type_name }}</a>
  </li>
</ul>

这似乎适用于@wrahim。

我认为原始代码的根本问题是active属性已添加到category属于Vue&#39; change detection caveats之一。

答案 1 :(得分:0)

这可以按预期工作。您的问题不在您发布的代码中。 (即使使用map:在地图中,对象也是引用,因此修改其成员会修改原始对象。)

new Vue({
  el: '#app',
  data: {
    categories: [{
        service_type_name: 'one',
        active: false
      },
      {
        service_type_name: 'two',
        active: false
      }
    ]
  },
  methods: {
    changeCategory(index) {
      this.categories.map((c, i) => {
        c.active = (i != index) ? false : true
      })
    }
  }
});
.active {
  background-color: lightgray;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script>
<ul id="app">
  <li v-for="category, i in categories" :class="{active: category.active}" @click="changeCategory(i)">
    <a>{{ category.service_type_name }}</a>
  </li>
</ul>