class Depend {
constructor() {
//set不允許重復(fù)
this.reactiveFns = new Set();
}
//添加對應(yīng)的依賴
addDepend(fn) {
if (fn) {
this.reactiveFns.add(fn);
}
}
depend() {
if (reactiveFn) {
this.reactiveFns.add(reactiveFn);
}
}
//通知數(shù)據(jù)發(fā)生變化,收集依賴
notify() {
this.reactiveFns.forEach((fn) => {
fn();
});
}
}
//定義一個函數(shù),專門執(zhí)行響應(yīng)式函數(shù)
//形成閉包
let reactiveFn = null;
function watchFn(fn) {
//一旦執(zhí)行函數(shù),將值賦值給reactiveFn
reactiveFn = fn;
fn();
//函數(shù)保存起來,默認執(zhí)行一次
//類似于wachEeffct(),自動收集依賴,立即執(zhí)行執(zhí)行一次
reactiveFn = null;
//執(zhí)行完操作之后,賦值為空,有可能對后續(xù)操作造成影響
}
//封裝一個函數(shù),來獲取對應(yīng)的depend對象
//利用weakMap,弱引用,即使obj為null,也不能對后續(xù)造成影響,
const objMap = new WeakMap();
function getDepend(obj, key) {
//根據(jù)對象obj,找到對應(yīng)的map對象
let map = objMap.get(obj);
if (!map) {
//weakMap的key必須要是對象,所以這里用Map()
//如果拿不到,我們就new一個
map = new Map();
objMap.set(obj, map);
}
//根據(jù)key,找到對應(yīng)的depend對象
let dep = map.get(key);
if (!dep) {
dep = new Depend();
map.set(key, dep);
}
//所以一定可以返回拿到一個dep對象
return dep;
}
//方案一。Object.defineProperty() -> Vue2
//對obj里面的數(shù)據(jù)進行遍歷
function reactive(obj) {
Object.keys(obj).forEach((key) => {
let value = obj[key];
//對每個key和set操作進行對應(yīng)劫持
Object.defineProperty(obj, key, {
set: function (newValue) {
//保存value值
value = newValue;
const dep = getDepend(obj, key);
//去通知更新
dep.notify();
},
get: function () {
// 拿到obj -> key
// 找到對應(yīng)的obj對象的key對應(yīng)的dep對象
const dep = getDepend(obj, key);
//間接的把函數(shù)添加進去
dep.depend();
return value;
},
});
});
return obj;
}
//----------------------
const obj = reactive({
name: "james",
age: 38,
});
//凡是傳進watchFn函數(shù)里面就是響應(yīng)式的
watchFn(function foo() {
console.log("foo name is", obj.name);
console.log("foo age is ", obj.age);
console.log("foo age is ", obj.age);
});
const user = reactive({
height: 188,
name: "peter",
});
watchFn(function bar() {
console.log("user height", user.height);
console.log("user name", user.name);
});
console.log("監(jiān)聽obj-age發(fā)生變化~~~~~~~~");
obj.age += 100;
console.log("監(jiān)聽name發(fā)生變化~~~~~~~~");
user.name += "123";
手寫vue2響應(yīng)式原理最終代碼
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 1、 數(shù)據(jù)響應(yīng)式 首先請大家認真的思考一個問題:什么是數(shù)據(jù)響應(yīng)式? 答:數(shù)據(jù)變化是可偵測的,并且和數(shù)據(jù)相關(guān)的內(nèi)容可...
- 這道題目是面試中相當(dāng)高頻的一道題目了,但凡你簡歷上有寫:“熟練使用Vue并閱讀過其部分源碼”,那么這道題目十有八九...
- 實現(xiàn)訂閱模型: //數(shù)據(jù)劫持 測試: 數(shù)據(jù)綁定: 更新或新增data中某屬性值,界面涉及到該屬性的節(jié)點都會更新。 ...
- 本文源碼版本 Vue3.2.11,Vue2 響應(yīng)式源碼剖析點這里 深入淺出 Vue2 響應(yīng)式原理源碼剖析[http...