實(shí)現(xiàn)一個(gè)簡單得數(shù)據(jù)響應(yīng)系統(tǒng)
1、Dep
其實(shí),這就是一個(gè)依賴收集的容器, depend 收集依賴, notify 觸發(fā)依賴
class Dep{
constructor() {
this._subs = [];
}
depend () {
this._subs.push(Dep.target)
}
notify() {
this._subs.forEach(item => {
item.fn();
})
}
}
// 其實(shí)就是 dep 和 watcher 基情滿滿的開始,watcher 中用到
// 通過一個(gè)全局屬性來存 watcher
Dep.target = null;
function pushTarget(watch) {
Dep.target = watch;
}
function popTarget() {
Dep.target = null;
}
2、了解 obverser
遞歸,將 data 對象所有屬性轉(zhuǎn)化為訪問器屬性
// 轉(zhuǎn)為訪問器屬性
function defineReactive (obj, key, val, shallow) {
// 創(chuàng)建一個(gè)依賴收集容器
let dep = new Dep();
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
if(Dep.target) {
// 收集依賴
dep.depend();
}
return val;
// ...
},
set: function reactiveSetter (newVal) {
if(newVal === val) return;
// 繼續(xù)遞歸遍歷
observe(newVal);
// 觸發(fā)依賴
dep.notify();
// ...
}
})
}
class Observer{
constructor(data) {
this.walk(data);
}
walk(data) {
const keys = Object.keys(data)
for (let i = 0; i < keys.length; i++) {
defineReactive(data, keys[i], data[keys[i]])
}
}
}
// 遞歸,將 data 對象所有屬性轉(zhuǎn)化為訪問器屬性
function observe (data) {
if(Object.prototype.toString.call(data) !== '[object Object]') return;
new Observer(data);
}
此時(shí)就可以把任意一個(gè)對象的全部屬性轉(zhuǎn)為訪問器
3、了解 watch 和 observer
const data = {
a: 1,
b: 2
}
// 首先監(jiān)控一個(gè)對象
observe(data);
watcher 的主要功能是檢測某個(gè)屬性,當(dāng)屬性變化時(shí)觸發(fā)一個(gè)回調(diào)
class Watcher{
/**
* @params {Function} exp 一個(gè)屬性表達(dá)式
* @params {Function} fn 回調(diào)
*/
constructor(exp, fn) {
this.exp = exp;
this.fn = fn;
// 存 watcher
// Dep.target = this;
pushTarget(this);
// 先執(zhí)行一次表達(dá)式函數(shù),會(huì)在調(diào)用過程中,
// 觸發(fā)到 data.a 的訪問器, data.a 的 get 被執(zhí)行,
// 觸發(fā) dep.depend() 開始收集依賴
this.exp();
// 釋放 Dep.target
popTarget();
}
}
// new Watcher 這樣一個(gè)依賴就被收集了
new Watcher(() => {
return data.a + data.b;
}, () => {
console.log('change')
})
4、觸發(fā)依賴
data.a = 3; // change data.b = 3; // change
5、總結(jié)一下流程
- 把一個(gè)對象的全部屬性轉(zhuǎn)化為訪問器
- 當(dāng)為某一個(gè)屬性增加
watcher時(shí),會(huì)觸發(fā)改屬性的get,get函數(shù)中會(huì)把該watcher存到該屬性的dep依賴容器中 - 當(dāng)這個(gè)屬性發(fā)生變化時(shí),會(huì)出發(fā)改屬性的
set的方法,set函數(shù)中會(huì)把dep存的依賴都執(zhí)行
到此這篇關(guān)于實(shí)現(xiàn)一個(gè)簡單得數(shù)據(jù)響應(yīng)系統(tǒng)的文章就介紹到這了,更多相關(guān)數(shù)據(jù)響應(yīng)系統(tǒng)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript前端迭代器Iterator與生成器Generator講解
這篇文章主要為大家介紹了JavaScript前端迭代器Iterator與生成器Generator講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
JavaScript架構(gòu)搭建前端監(jiān)控如何采集異常數(shù)據(jù)
這篇文章主要為大家介紹了JavaScript架構(gòu)搭建前端監(jiān)控如何采集異常數(shù)據(jù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
js實(shí)現(xiàn)兔年轉(zhuǎn)圈圈動(dòng)畫示例
這篇文章主要為大家介紹了js實(shí)現(xiàn)兔年轉(zhuǎn)圈圈動(dòng)畫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
微信小程序 網(wǎng)絡(luò)API發(fā)起請求詳解
這篇文章主要介紹了微信小程序 網(wǎng)絡(luò)API發(fā)起請求詳解的相關(guān)資料,需要的朋友可以參考下2016-11-11
JS實(shí)現(xiàn)大數(shù)相加大數(shù)相乘示例詳解
這篇文章主要為大家介紹了JS實(shí)現(xiàn)大數(shù)相加大數(shù)相乘示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
自定義range?sliders滑塊實(shí)現(xiàn)元素拖動(dòng)方法
這篇文章主要為大家介紹了自定義range?sliders滑塊實(shí)現(xiàn)元素拖動(dòng)方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
JavaScript 運(yùn)行機(jī)制詳解再淺談Event Loop
這篇文章主要介紹了JavaScript 運(yùn)行機(jī)制詳解及淺談了Event Loop,感興趣的小伙伴可以和小編一起閱讀下面文章的具體內(nèi)容2021-09-09

