使用uniapp写项目的时候, 碰到一个问题, 给后端传来的对象数组中的对象添加属性时, 无法实现动态响应, 以为是uniapp内部的问题, 于是我将同样的代码在vue中运行(uniapp和vue语法相同), 依然无法实现动态响应
<template>
<div class="type-chose">
<div class="type-chose-left">
<div
v-for="item in dataList"
:class="item.chose_status === true ? 'itemActive' : ''"
@click="dealItemClick(item)"
:key="item.id"
>{
{
item.name}}
</div>
</div>
</div>
</template>
<script>
export default {
name: "Test1",
data() {
return {
dataList: [
{
"id": 1,
"name": "小时工",
},
{
"id": 2,
"name": "开荒保洁",
},
{
"id": 3,
"name": "擦玻璃",
},
{
"id": 4,
"name": "除甲醛",
},
],
}
},
mounted() {
for (let obj of this.dataList) {
obj.chose_status = false;
}
},
methods: {
dealItemClick(item) {
item.chose_status = true;
for (let obj of this.dataList) {
if (obj !== item) obj.chose_status = false;
}
console.log(this.dataList);
},
},
}
</script>
点列表中的某个选项, 样式改变
点击最后一个选项, chose_status为true, 但是样式没有发生改变
查阅vue官方文档:vue的响应式底层原理
关键点是:
由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
对于对象: Vue无法检测 property 的添加或移除, 由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
也就是说: 如果你在Vue实例化后, 再为某一个对象进行增加或删除属性, 那么vue就无法让这个属性变为响应式的, 上述代码中, 由于是后来才对这个对象数组中的对象进行增加属性, 所以chose_status这个属性不是响应式的, 所以点击某个选项, 样式没有改变。
使用
Vue.set(object, propertyName, value)
或
this.$set(object, propertyName, value)
为对象添加响应式属性。 修改mounted中的代码如下:
for (let obj of this.dataList) {
this.$set(obj, 'chose_status' ,false);
}
这是对于对象的属性添加, 对于数组的, 查阅官方文档即可, 当然这个功能也可以使用activeId来实现。