Vue 中 $set() 与 Vue.set() 原理及使用

如题所述

第1个回答  2022-07-13

问题: 在使用 vue 进行开发的过程中,可能会遇到一种情况:当生成vue实例后,再次给数据赋值时,有时候并不会自动更新到视图上去。也就是 如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。

案例:

当点击按钮后页面:
[图片上传失败...(image-377e69-1637720296752)]

当点击按钮后控制台:

原因:
受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以 属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的。

因此:
Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
eg:
使用 this.arr[0] 去更新 array 的内容,视图没有刷新
使用 Vue.set(this.arr, 0, !this.arr[0]) 去更新 array 的内容,视图被刷新
使用 this.arr[0] = !this.arr[0] 和 this.obj.a = !this.obj.a 同时更新,视图被刷新

结论:
如果方法里面单纯的更新数组 Array 的话,要使用 Vue.set();
如果方法里面同时有数组和对象的更新,直接操作 data 即可;

每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

受现代 JavaScript 的限制 (而且 Object.observe 也已经被废弃),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

3.1 通过 Vue.set() 改写
语法:

当点击按钮后页面:
[图片上传失败...(image-6f4696-1637720296752)]

当点击按钮后控制台:

3.2 通过 $set() 改写
语法:

当点击按钮后页面:

当点击按钮后控制台:

3.3 Vue.set() 和 this.$set() 的区别

Vue.set() 源码:

this.$set() 源码

文章转自 Vue 中 $set() 与 Vue.set() 原理及使用

相似回答