Vue $set 源码解析

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


首先我们看文档有这个例子

Vue $set 源码解析_javascript

 

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()

上面这一段 是 vue $set 的源码

if (process.env.NODE_ENV !== 'production' && (isUndef(target) || isPrimitive(target)) ) { warn(`Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}`) }

我们先看第一段代码 isUndef和isPrimitive方法,从名字就可以看出,isUndef是判断target是不是等于undefined或者null。isPrimitive是判断target的数据类型是不是string、number、symbol、boolean中的一种。所以这里的意思是如果当前环境不是生产环境并且 isUndef(target) || isPrimitive(target) 为真的时候,那么就抛出错误警告。

if (Array.isArray(target) && isValidArrayIndex(key)) {
target.length = Math.max(target.length, key)
target.splice(key, 1, val)
return val
}

接着我们看第二段 

isArray 判断是不是数组,并且key的值是有效的数组索引。

然后将target数组的长度设置为target.length和key中的最大值,为了防止我们传入key下标超过数组长度导致报错。

尤玉溪重写了vue 的原型 arrayMethods 里面监听了七个方法 他文档上有提到

这里使用splice是arrayMethods提供的7个方法中的一种 来做到替换数组的数据

if (key in target && !(key in Object.prototype)) {
target[key] = val
return val
}

我们来看第三段 

他判断了这个key是不是当前对象的key 和 这个key 不是object原型的key

说明这个key本来就在对象上面已经定义过了的,直接修改值就可以了,可以自动触发响应。

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
}

我们来看第四段

我们可以看到 他给对象添加了一个__obj__属性如果一个对象有这个__ob__属性,那么就说明这个对象是响应式对象,我们修改对象已有属性的时候就会触发页面渲染

if (!ob)为真说明当前的target对象不是响应式对象,不需要响应,那么直接赋值返回即可

defineReactive(ob.value, key, val)
ob.dep.notify()
return val

最后一段

这里才是vue.set()真正处理对象的地方。defineReactive(ob.value, key, val)```的意思是给新加的属性添加依赖,以后再直接修改这个新的属性的时候就会触发页面渲染。 ​ob.dep.notify()​这句代码的意思是触发当前的依赖(这里的依赖依然可以理解成渲染函数),所以页面就会进行重新渲染。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue