vue2源码-- Vue.set和Vue.delete
Posted 在厕所喝茶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue2源码-- Vue.set和Vue.delete相关的知识,希望对你有一定的参考价值。
目录
Vue.set
作用
给对象或者数组添加一个新的属性。如果对象或者数组是一个响应式数据,那么,新添加的属性也将会变成响应式数据,并且触发视图更新。
原理分析
1、如果target
对象为原始类型
或者undefined
、null
,则警告报错
2、如果是数组,并且下标索引是有效的合法值,就会取原数组的长度和传入的下标索引值的最大值作为数组的长度,然后调用splice
方法添加数据,因为splice
方法被重写了,会把元素自动转化为响应式,并通知更新。返回val
值
3、如果是对象,并且key
值已经在目标对象上面了,直接赋值即可,并返回
4、如果key
值不在目标对象上面,先判断目标对象是否为 vue 实例或者 vue 实例的根数据独享,是,则报错,退出程序;然后在判断目标对象上面的__ob__
属性是否存在,不存在,说明目标对象并不是一个响应式数据,直接赋值,并退出程序。最后通过调用defineReactive
函数添加新属性,并转化为响应式数据,通知更新,退出程序
注意:为什么数组不需要判断__ob__
属性是否存在?因为如果是数组是一个响应式数据,那么,调用splice
方法是重写过后的,如果不是响应式数据,那么,splice
方法是原生的数组方法
源码
源码位于src/core/observer/index.js
,第208
行
export function set (target: Array<any> | Object, key: any, val: any): any
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
)
// target为原始类型或者undefined、null,报错
warn(`Cannot set reactive property on undefined, null, or primitive value: $target`)
// isValidArrayIndex(key)判断索引是否为有效值
if (Array.isArray(target) && isValidArrayIndex(key))
// 数组的情况
// 对比2个索引的,取最大的索引作为数组的长度
target.length = Math.max(target.length, key)
// 使用splice方法添加数据,因为splice方法被重写了,会把元素自动转化为响应式
target.splice(key, 1, val)
return val
// 不是数组就当做对象处理
if (key in target && !(key in Object.prototype))
// 如果key已经在target上了,直接赋值即可
target[key] = val
return val
const ob = target.__ob__
if (target._isVue || (ob && ob.vmCount))
// 如果target是vue实例或者vue实例的根数据独享,则报错,退出程序
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)
// ob不存在,说明target不是一个响应式数据
// 直接赋值即可
target[key] = val
return val
// 调用defineReactive方法添加新属性,并转化为响应式数据
defineReactive(ob.value, key, val)
// 通知更新
ob.dep.notify()
return val
Vue.delete
作用
删除对象或者数组中的属性。如果对象或者数组是一个响应式的数据,会触发视图的更新
原理分析
1、如果target
对象为原始类型
或者undefined
、null
,则警告报错
2、如果目标对象是数组,并且下标索引值为有效的,则调用splice
方法进行删除
3、如果目标对象是 vue 实例或者是 vue 实例的根数据,则退出,并报错提示
4、如果 key 本来就不存在与目标对象中,则退出函数,什么都不用干
5、使用delete
关键字删除属性值,
6、通知更新
源码
源码位于src/core/observer/index.js
,第256
行
export function del (target: Array<any> | Object, key: any)
if (process.env.NODE_ENV !== 'production' &&
(isUndef(target) || isPrimitive(target))
)
// target不存在或者是原始值的情况下,报错
warn(`Cannot delete reactive property on undefined, null, or primitive value: $target`)
if (Array.isArray(target) && isValidArrayIndex(key))
// 有效key则使用splice进行删除
target.splice(key, 1)
return
const ob = target.__ob__
if (target._isVue || (ob && ob.vmCount))
// 不能是vue实例或者是vue实例的根数据
process.env.NODE_ENV !== 'production' && warn(
'Avoid deleting properties on a Vue instance or its root $data ' +
'- just set it to null.'
)
return
if (!hasOwn(target, key))
// 本来就不存在于target对象中的,就不用删除
return
// 删除属性值
delete target[key]
if (!ob)
return
// 如果是一个响应式的情况下,通知更新
ob.dep.notify()
以上是关于vue2源码-- Vue.set和Vue.delete的主要内容,如果未能解决你的问题,请参考以下文章