vue3簡(jiǎn)易實(shí)現(xiàn)proxy代理實(shí)例詳解
vue3 簡(jiǎn)易實(shí)現(xiàn)proxy代理
1.基礎(chǔ)數(shù)據(jù)
const state = reactive({ name: 'cld', age: 26, like: 'paint' });
console.log("獲取更改age前的值", state.age);
state.age = 28;
console.log("獲取更改age后的值", state.age);
核心邏輯 reactive
export function reactive (target) {
// 創(chuàng)建一個(gè)響應(yīng)式對(duì)象 對(duì)象 set map array object ...
return createReactiveObject(target, {
// proxy + reflect
get (target, key, receiver) {
// 可能無(wú)法訪問(wèn)key target[key]是否成功不會(huì)報(bào)錯(cuò) 所以使用reflect
const res = Reflect.get(target, key, receiver); // == target[key];
console.log('用戶取值', target, key);
return res;
},
set (target, key, value, receiver) {
const res = Reflect.set(target, key, value, receiver);
console.log('用戶設(shè)置值', target, key);// == target[key]=value;
return res;
}
});
}
const isObject = (obj) => { return typeof obj == 'object' && obj != null; };
function createReactiveObject (target, baseHandler) {
// 如果不是對(duì)象 不需要代理
if (!isObject(target)) {
return target;
}
// target目標(biāo)對(duì)象 baseHandler get/set 值處理方法,
const observed = new Proxy(target, baseHandler);
return observed;
}
/** Reflect 作用 * 可能無(wú)法訪問(wèn)key target[key]是否成功不會(huì)報(bào)錯(cuò) * 所以使用reflect * Reflect.get 返回值 Reflect.set 返回值boolean **/ const res = Reflect.get(target, key, receiver); // Reflect.get(target, key, receiver); 等價(jià)于 target[key] 并返回值 const res = Reflect.set(target, key, value, receiver); // res 值為true/false 表示是否成功設(shè)置值
代理實(shí)現(xiàn)效果

vue3取值的時(shí)候才走代理操作,不取值的時(shí)候,不需要深度遍歷代理,
vue2一開(kāi)始就深度遞歸
當(dāng)數(shù)據(jù)里為數(shù)組或?qū)ο蟮那闆r下,需要遞歸代理
get (target, key, receiver) {// proxy+reflect
const res = Reflect.get(target, key, receiver);// == target[key];
if (isObject(res)) {
return reactive(res);
}
return res;
};
修改值的時(shí)候,具體是新增操作還是修改操作 可以定位
set (target, key, value, receiver) {
const hasKey = hasOwn(target, key);
const oldValue = target[key]; // Reflect.set 操作前還是歷史數(shù)據(jù)
const res = Reflect.set(target, key, value, receiver);
if (!hasKey) {
// 新增屬性
console.log('用戶新增值', target, key);
} else if (value !== oldValue) {
//修改操作
console.log('用戶修改值', target, key);
}
return res;
};
push數(shù)據(jù)的時(shí)候,會(huì)先取arr的push屬性,然后取array的length屬性

設(shè)置值的時(shí)候 key是index索引,在該索引上增加值

其實(shí)在該索引上增加值之后,還會(huì)再次觸發(fā)set 應(yīng)該數(shù)組的長(zhǎng)度改變了
為了減少多余的無(wú)必要的操作,可以通過(guò)判斷不執(zhí)行任何操作
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
vue實(shí)現(xiàn)行列轉(zhuǎn)換的一種方法
這篇文章主要介紹了vue實(shí)現(xiàn)行列轉(zhuǎn)換的一種方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
vue自動(dòng)化路由的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue自動(dòng)化路由的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
vue移動(dòng)端使用canvas簽名的實(shí)現(xiàn)
這篇文章主要介紹了vue移動(dòng)端使用canvas簽名的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
Template?ref在Vue3中的實(shí)現(xiàn)原理詳解
這篇文章主要為大家介紹了Template?ref在Vue3中的實(shí)現(xiàn)原理示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
詳解使用VueJS開(kāi)發(fā)項(xiàng)目中的兼容問(wèn)題
這篇文章主要介紹了詳解使用VueJS開(kāi)發(fā)項(xiàng)目中的兼容問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
使用v-memo緩存模板子樹(shù)提高應(yīng)用性能詳解
這篇文章主要為大家介紹了使用v-memo緩存模板子樹(shù)提高應(yīng)用性能詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
vue框架下部署上線后刷新報(bào)404問(wèn)題的解決方案(推薦)
這篇文章主要介紹了vue框架下部署上線后刷新報(bào)404問(wèn)題解決方案,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04

