通過Proxy(代理): 攔截對data任意屬性的任意(13種)操作, 包括屬性值的讀寫, 屬性的添加, 屬性的刪除等...
通過 Reflect(反射): 動態(tài)對被代理對象的相應(yīng)屬性進行特定的操作
// shallowReactive(淺的劫持,淺的監(jiān)視,淺的響應(yīng)數(shù)據(jù)) 與 reactive(深的)
// 定義一個reactiveHandler處理對象
const reactiveHandler = {
// 獲取屬性值
get (target, prop) {
if (prop === '_is_reactive') return true
const result = Reflect.get(target, prop)
console.log('攔截了讀取數(shù)據(jù)', prop, result)
return result
},
// 修改屬性值或者是添加屬性
set (target, prop, value) {
const result = Reflect.set(target, prop, value)
console.log('攔截了修改數(shù)據(jù)或者是添加屬性', prop, value)
return result
},
// 刪除某個屬性
deleteProperty (target, prop) {
const result = Reflect.deleteProperty(target, prop)
console.log('攔截了刪除數(shù)據(jù)', prop)
return result
}
}
// 定義一個shallowReactive函數(shù),傳入一個目標對象
function shallowReactive (target) {
// 判斷當(dāng)前的目標對象是不是object類型(對象/數(shù)組)
if (target && typeof target === 'object') {
return new Proxy(target, reactiveHandler)
}
// 如果傳入的數(shù)據(jù)是基本類型的數(shù)據(jù),那么就直接返回
return target
}
// 定義一個reactive函數(shù),傳入一個目標對象
function reactive (target) {
// 判斷當(dāng)前的目標對象是不是object類型(對象/數(shù)組)
if (target && typeof target === 'object') {
// 對數(shù)組或者是對象中所有的數(shù)據(jù)進行reactive的遞歸處理
// 先判斷當(dāng)前的數(shù)據(jù)是不是數(shù)組
if (Array.isArray(target)) {
// 數(shù)組的數(shù)據(jù)要進行遍歷操作
target.forEach((item, index) => {
target[index] = reactive(item)
})
} else {
// 再判斷當(dāng)前的數(shù)據(jù)是不是對象
// 對象的數(shù)據(jù)也要進行遍歷的操作
Object.keys(target).forEach(key => {
target[key] = reactive(target[key])
})
}
return new Proxy(target, reactiveHandler)
}
// 如果傳入的數(shù)據(jù)是基本類型的數(shù)據(jù),那么就直接返回
return target
}
// =================================
// 定義了一個readonlyHandler處理器
const readonlyHandler = {
get (target, prop) {
if (prop === '_is_readonly') return true
const result = Reflect.get(target, prop)
console.log('攔截到了讀取數(shù)據(jù)了', prop, result)
return result
},
set (target, prop, value) {
console.warn('只能讀取數(shù)據(jù),不能修改數(shù)據(jù)或者添加數(shù)據(jù)')
return true
},
deleteProperty (target, prop) {
console.warn('只能讀取數(shù)據(jù),不能刪除數(shù)據(jù)')
return true
}
}
// 定義一個shallowReadonly函數(shù)
function shallowReadonly (target) {
// 需要判斷當(dāng)前的數(shù)據(jù)是不是對象
if (target && typeof target === 'object') {
return new Proxy(target, readonlyHandler)
}
return target
}
// 定義一個readonly函數(shù)
function readonly (target) {
// 需要判斷當(dāng)前的數(shù)據(jù)是不是對象
if (target && typeof target === 'object') {
// 判斷target是不是數(shù)組
if (Array.isArray(target)) {
// 遍歷數(shù)組
target.forEach((item, index) => {
target[index] = readonly(item)
})
} else { // 判斷target是不是對象
// 遍歷對象
Object.keys(target).forEach(key => {
target[key] = readonly(target[key])
})
}
return new Proxy(target, readonlyHandler)
}
// 如果不是對象或者數(shù)組,那么直接返回
return target
}
// 定義一個shallowRef函數(shù)
function shallowRef (target) {
return {
// 保存target數(shù)據(jù)保存起來
_value: target,
get value () {
console.log('劫持到了讀取數(shù)據(jù)')
return this._value
},
set value (val) {
console.log('劫持到了修改數(shù)據(jù),準備更新界面', val)
this._value = val
}
}
}
// 定義一個ref函數(shù)
function ref (target) {
target = reactive(target)
return {
_is_ref: true, // 標識當(dāng)前的對象是ref對象
// 保存target數(shù)據(jù)保存起來
_value: target,
get value () {
console.log('劫持到了讀取數(shù)據(jù)')
return this._value
},
set value (val) {
console.log('劫持到了修改數(shù)據(jù),準備更新界面', val)
this._value = val
}
}
}
// 定義一個函數(shù)isRef,判斷當(dāng)前的對象是不是ref對象
function isRef (obj) {
return obj && obj._is_ref
}
// 定義一個函數(shù)isReactive,判斷當(dāng)前的對象是不是reactive對象
function isReactive (obj) {
return obj && obj._is_reactive
}
// 定義一個函數(shù)isReadonly,判斷當(dāng)前的對象是不是readonly對象
function isReadonly (obj) {
return obj && obj._is_readonly
}
// 定義一個函數(shù)isProxy,判斷當(dāng)前的對象是不是reactive對象或者readonly對象
function isProxy (obj) {
return isReactive(obj) || isReadonly(obj)
}