理解Vue中响应式数据
Posted 前端茅台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解Vue中响应式数据相关的知识,希望对你有一定的参考价值。
数组和对象类型当值变化时如何劫持到?
a、对象通过Object.defineProperty将属性进行劫持;多重对象通过递归进行实现。
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: ?Function,
shallow?: boolean
) {
// 1.如果对象不可配置则直接退出
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
}
// 2.获取getter和setter
const getter = property && property.get
const setter = property && property.set
// 3.重新定义set和get方法
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
const value = getter ? getter.call(obj) : val
return value
},
set: function reactiveSetter (newVal) {
const value = getter ? getter.call(obj) : val
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
}
})
}
这种方式只会监听对象自带的属性,新增的属性监听不到,因此对于新增的属性使用$set方式进行数据新增,$set方法内部会将新增属性定义成响应式数据
b、数组通过重写方法
export const arrayMethods = Object.create(arrayProto)
const methodsToPatch = [
\'push\',
\'pop\',
\'shift\',
\'unshift\',
\'splice\',
\'sort\',
\'reverse\'
]
methodsToPatch.forEach(function (method) {
// cache original method
const original = arrayProto[method]
def(arrayMethods, method, function mutator (...args) {
const result = original.apply(this, args)
const ob = this.__ob__
let inserted
switch (method) {
case \'push\':
case \'unshift\':
inserted = args
break
case \'splice\':
inserted = args.slice(2)
break
}
// 对新增的属性再次进行观测
if (inserted) ob.observeArray(inserted)
return result
})
})
当操作数组时会调用重写的数组方法,这时就可以监测到数据的变化。因此,如果修改数组索引和长度是不会监听到数组的变化的。
Vue3中使用ES6的Proxy代理,Proxy可以拦截目标对象的底层操作
let obj = {
name: {name: \'lh\'}
}
let handler = {
get(target,key){ // 这里的命名必须和Reflect方法对应
if(typeof target[key] === \'object\' && target[key] !== null){
return new Proxy(target[key],handler);
}
return Reflect.get(target,key);
},
set(target,key,value){
let oldValue = target[key];
if(!oldValue){
console.log(\'新增属性\')
}else if(oldValue !== value){
console.log(\'修改属性\')
}
return Reflect.set(target,key,value);
}
}
let proxy = new Proxy(obj,handler);
以上是关于理解Vue中响应式数据的主要内容,如果未能解决你的问题,请参考以下文章