/**
* 響應式
*/
function reactive(target) {
return createReactiveObject(target)
}
/**
* 已代理過原始值與代理後的值 hashMap
*/
const rawToReactive = new WeakMap()
const reactiveToRaw = new WeakMap()
const effectStack=[]
/**
* 創建響應式對象
*/
function createReactiveObject(target) {
if (!isObject(target)) {
return target
}
// 防止對象被重複代理
let proxy = rawToReactive.get(target)
if (proxy) {
return proxy
}
// 防止代理又被代理
if (reactiveToRaw.has(target)) {
return target
}
let baseHandler = {
get(target, key, receiver) {
console.log('獲取')
let res = Reflect.get(target, key, receiver)
// track(target,key)// 收集依賴
// res是當前獲取到的值
return isObject(res) ? reactive(res) : res
},
set(target, key, value, receiver) {
// console.log('設置')
// 識別改屬性還是新增屬性
let hasKey = hasOwn(target, key)
let oldValue = target[key]
if (!hasKey) {
console.log('新增屬性')
} else if (oldValue !== value) {
console.log('修改屬性')
}
let res = Reflect.set(target, key, value, receiver)
return res
},
deletePrototype(target, key) {
console.log('刪除')
let res = Reflect.deleteProperty(target, key)
return res
}
}
let observed = new Proxy(target, baseHandler) // proxy兼容性差
rawToReactive.set(target, observed)
reactiveToRaw.set(observed, target)
return observed
}
/**
* 判斷是否是對象
*/
function isObject(target) {
return typeof target === 'object' && target !== null
}
function hasOwn(target, key) {
return target.hasOwnProperty(key)
}
let proxy = reactive({
name: 'tom',
age: {
n: 300
},
children: [1, 2, 3, 4]
})
// proxy.name = 'jack'
proxy.age.n = 500 // 先獲取age 再設置n
// proxy.children.push(5)
console.log(proxy)
let arr = [1, 2, 3]
let proxy = reactive(arr)
proxy.push(4)
// 先添加元素4
// 再更改length
Vue3 數據劫持原理
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.