vue2.x 数组或者对象新增数据改变页面不刷新

在日常开发过程中,经常遇到数组新增或者对象新增属性数据打印刷新,但是vue视图确不刷新,这个有几种解决办法,下满我们先来说下为什么不刷新视图,再介绍下几种解决方法:
在这里插入图片描述
直接添加属性的问题:
首先定义一个p标签,通过v-for指令进行遍历

然后给botton标签绑定点击事件,我们预期点击按钮时,数据新增一个属性,界面也 新增一行

<p v-for="(value,key) in item" :key="key">
    {{ value }}
</p>
<button @click="addProperty">动态添加新属性</button>

实例化一个vue实例,定义data属性和methods方法

const app = new Vue({
    el:"#app",
   	data:()=>{
       	item:{
            oldProperty:"旧属性"
        }
    },
    methods:{
        addProperty(){
            this.items.newProperty = "新属性"  // 为items添加新属性
            console.log(this.items)  // 输出带有newProperty的items
        }
    }
})

点击按钮,发现结果不及预期,数据虽然更新了(console打印出了新属性),但页面并没有更新。

原理:
vue2是用过Object.defineProperty实现数据响应式。

const obj = {}
Object.defineProperty(obj, 'foo', {
        get() {
            console.log(`get foo:${val}`);
            return val
        },
        set(newVal) {
            if (newVal !== val) {
                console.log(`set foo:${newVal}`);
                val = newVal
            }
        }
    })
}

当我们访问foo属性或者设置foo值的时候都能够触发setter与getter。但是我们可以看到,obj里只有get , set 上并没有新增触发监听,所以我们为obj添加新属性的时候,却无法触发事件属性的拦截

解决方法 :
若想实现数据与视图同步更新,可采取下面三种解决方案:

Vue.set()
Object.assign()
$forcecUpdated()

**

vue.set()

**:Vue.set( target, propertyName/index, value )
通过Vue.set向响应式对象中添加一个property,并确保这个新 property 同样是响应式的,且触发视图更新

关于Vue.set源码(省略了很多与本节不相关的代码)

源码位置:src\core\observer\index.js

function set (target: Array<any> | Object, key: any, val: any): any {
  ...
  defineReactive(ob.value, key, val)
  ob.dep.notify()
  return val
}

这里无非再次调用defineReactive方法,实现新增属性的响应式

关于defineReactive方法,内部还是通过Object.defineProperty实现属性拦截

大致代码如下:

function defineReactive(obj, key, val) {
    Object.defineProperty(obj, key, {
        get() {
            console.log(`get ${key}:${val}`);
            return val
        },
        set(newVal) {
            if (newVal !== val) {
                console.log(`set ${key}:${newVal}`);
                val = newVal
            }
        }
    })
}

Object.assign()

直接使用Object.assign()添加到对象的新属性不会触发更新

应创建一个新的对象,合并原对象和混入对象的属性

this.someObject = Object.assign({},this.someObject,{newProperty1:1,newProperty2:2 ...})

$forceUpdate

$forceUpdate迫使 Vue 实例重新渲染

PS:仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。

总结:如果为对象添加少量的新属性,可以直接采用Vue.set()
如果需要为新对象添加大量的新属性,则通过Object.assign()创建新对象
如果你实在不知道怎么操作时,可采取$forceUpdate()进行强制刷新 (不建议)

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值