1.1 如何实现响应式数据
数组和对象类型当值变化时如何劫持到。对象内部通过defineReactive
方法,使用Object.defineProperty
将属性进行劫持(只会劫持已经存在的属性),数组则是通过重写数组方法来实现。 多层对象是通过递归来实现劫持。Vue3
则采用 proxy
1.2 vue2
处理缺陷
- 在
Vue2
的时候使用defineProperty
来进行数据的劫持, 需要对属性进行重写添加getter
及setter
性能差。 - 当新增属性和删除属性时无法监控变化。需要通过
$set
、$delete
实现 - 数组不采用
defineProperty
来进行劫持 (浪费性能,对所有索引进行劫持会造成性能浪费)需要对数组单独进行处理。 - 对于
ES6
中新产生的 Map、Set 这些数据结构不支持。
1.3 Vue2
与 Vue3
实现对比
Vue2
function defineReactive(target,key,value){
observer(value);
Object.defineProperty(target,key,{ ¸v
get(){
//依赖收集
return value;
},
set(newValue){
if (value !== newValue) {
value = newValue;
observer(newValue)
}
}
})
}
function observer(data) {
if(typeof data !== 'object'){
return data
}
// 依赖更新
for(let key in data){
defineReactive(data,key,data[key]);
}
}
vue3
let handler = {
get(target, key) {
if (typeof target[key] === "object") {
return new Proxy(target[key], handler)
}
return Reflect.get(target, key)
},
set(target, key, value) {
let oldValue = target[key]
if (oldValue !== value) {
return Reflect.set(target, key, value)
}
return true
},
}
let proxy = new Proxy(obj, handler)