如何在 v-for 渲染的对象内发生更改时更新 DOM?
How to update DOM when changes occurs within an object rendered by 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 添加到其中(因为模板中的 :class="{active: category.active}"
行。
但是,DOM 未更新以显示此更改。
是否可以在发生此更改时自动更新 DOM,而无需在 changeCategory(index)
函数中使用 this.$forceUpdate()
?
编辑:将map
更改为forEach
,DOM仍然没有更新。
编辑:我正在使用 vue-class-components 和 typescript
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
})
}
}
这按预期工作。您的问题不在您在此处发布的代码中。 (即使使用 map:在 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>
在讨论这个问题后,我提出了以下替代方法。
将 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 的 change detection caveats.[=16 之一=]
我正在使用 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 添加到其中(因为模板中的 :class="{active: category.active}"
行。
但是,DOM 未更新以显示此更改。
是否可以在发生此更改时自动更新 DOM,而无需在 changeCategory(index)
函数中使用 this.$forceUpdate()
?
编辑:将map
更改为forEach
,DOM仍然没有更新。
编辑:我正在使用 vue-class-components 和 typescript
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
})
}
}
这按预期工作。您的问题不在您在此处发布的代码中。 (即使使用 map:在 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>
在讨论这个问题后,我提出了以下替代方法。
将 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 的 change detection caveats.[=16 之一=]