写点什么

Vue 进阶(九十八):Vue.set() 和 this.$set()

用户头像
华强
关注
发布于: 11 小时前

一、应用场景

有时候我们会看到如下代码:



在我们使用vue进行开发的过程中,可能会遇到这样一种情况:当创建vue实例后,再次给对象赋值时,发现数据并不会自动更新到视图上去; 当我们去阅读vue文档的时候,会发现有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。 如下代码,给 student 对象新增 age 属性。


data () {  return {    student: {      name: '',      sex: ''    }  }}mounted () { // ——钩子函数,实例挂载之后  this.student.age = 24}
复制代码

二、原因分析

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


正确写法:this.$set(this.data,”key”,value')


mounted () {  this.$set(this.student,"age", 24)}
复制代码


Vue 不允许动态添加根级响应式属性。


例如:


const app = new Vue({  data: {    a: 1  }  // render: h => h(Suduko)}).$mount('#app1')
Vue.set(app.data, 'b', 2)
复制代码


此时控制台会报错:



只可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性,例如


var vm=new Vue({    el:'#test',    data:{        //data中已经存在info根属性        info:{            name:'小明';        }    }});//给info添加一个性别属性Vue.set(vm.info,'sex','男');
复制代码


有童鞋可能会问之前使用过Vue.set()this.$set()Vue.set有什么联系呢?

三、Vue.set() 和 this.$set() 实现原理

源码分析


先来看看Vue.set()源码:


import { set } from '../observer/index'
...Vue.set = set...
复制代码


再看看this.$set()源码:


import { set } from '../observer/index'
...Vue.prototype.$set = set...
复制代码


我们发现Vue.set()和this.$set()这两个api的实现原理基本一模一样,都使用了set()set()函数是从 ../observer/index 文件中导出的,区别在于:Vue.set()是将set函数绑定在Vue构造函数上,this.$set()set函数绑定在Vue原型上。


再来看下set源码:


function set (target: Array<any> | Object, key: any, val: any): any {
if (process.env.NODE_ENV !== 'production' && (isUndef(target) || isPrimitive(target)) ) { warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`) } if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key) target.splice(key, 1, val) return val } if (key in target && !(key in Object.prototype)) { target[key] = val return val } const ob = (target: any).__ob__ if (target._isVue || (ob && ob.vmCount)) { process.env.NODE_ENV !== 'production' && warn( 'Avoid adding reactive properties to a Vue instance or its root $data ' + 'at runtime - declare it upfront in the data option.' ) return val } if (!ob) { target[key] = val return val } defineReactive(ob.value, key, val) ob.dep.notify() return val}
复制代码


我们发现set函数接收三个参数分别为 target、key、val,其中target的值为数组或者对象,这正好和官网给出的调用Vue.set()时传入的参数对应上。


拓展阅读

发布于: 11 小时前阅读数: 3
用户头像

华强

关注

No Silver Bullet 2021.07.09 加入

岂曰无衣 与子同袍

评论

发布
暂无评论
Vue进阶(九十八):Vue.set() 和 this.$set()