解决Vue中的对象属性无法实现动态响应

问题描述:

使用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中的对象属性无法实现动态响应_第1张图片
解决Vue中的对象属性无法实现动态响应_第2张图片

原因分析:

查阅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来实现。

你可能感兴趣的:(前端,Vue,响应式,vue.js,前端)