摘要:今天想簡單聊聊的和函數(shù)。的作用是使一個普通的對象,變得可觀察。下面來看看的簡單實現(xiàn),這里不考慮對象的嵌套。一旦任何值發(fā)生了修改,就去執(zhí)行傳入的方法。有點簡單粗暴,是不是。并且把設(shè)為,表示需要收集依賴了。
今天想簡單聊聊mobx的observable和autoRun函數(shù)。不了解es6的proxy和reflect的伙伴,需要先看看這方面的知識點。
1、observable
observable的作用是使一個普通的對象,變得可觀察。也就是說當(dāng)一個對象變得可觀察了之后,當(dāng)你改變對象里的一個值的時候,就會去觸發(fā)對應(yīng)的有這個引用的autoRun函數(shù)。
下面來看看observable的簡單實現(xiàn),這里不考慮對象的嵌套。就假設(shè)它只有一層。方便理解概念。
var globalID = 0 function observable(obj) { var oID = ++globalID return new Proxy(obj, { get: function (target, key, receiver) { collect.startCollect(oID + "" +key) return Reflect.get(target, key, receiver) }, set: function (target, key, value, receiver) { Reflect.set(target, key, value, receiver) collection[oID + "" + key] && collection[oID + "" + key].forEach(c => { c() }); } }) }
observable的解釋在此:引用阮一峰的es6教程里的話
Proxy 可以理解成,在目標對象之前架設(shè)一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
這里用Proxy是因為當(dāng)你在可觀察對象上加入新的屬性時,就不會像Object.defineProperty那樣新的屬性沒法監(jiān)聽了。
像上面代碼那樣,咱們就成功的攔截了一個對象的getter和setter了。
每次當(dāng)你obj.a或者obj.b的時候都會進入get方法。咱們在返回obj.a,之前都會去收集依賴。至于到底要不要收集依賴,我這里是由collect.startCollect去判斷的。
每當(dāng)你obj.a = "balabala"的時候,咱們也攔截了set方法。在寫入值的之后,就要搞事情了,偷偷地去把收集來的依賴相應(yīng)的依賴,給全部執(zhí)行一遍(如果確實有的話)。
2、autoRun
一旦任何值發(fā)生了修改,就去執(zhí)行傳入autoRun的方法。
function autorun(handler) { collect.begin(handler) handler() collect.end() }
有點簡單粗暴,是不是。開始收集依賴了,我先發(fā)個信號。然后把autoRun里的handler給執(zhí)行一遍。最后,打聲招呼:小朋友你已經(jīng)兌過獎了,回家吧。執(zhí)行collect.end()。
3、collect
看了上面兩個,心里在想那個collect到底是個什么鬼?
var collection = {} var collect = { begin: function(handler) { collection.handler = handler collection.now = true }, startCollect: function(oIDKey) { if (collection.now) { if (collection[oIDKey]) { collection[oIDKey].push(collection.handler) } else { collection[oIDKey] = [collection.handler] } } }, end: function() { collection.now = false } }
這里的collection我也就寫在全局了,簡單粗暴。
在autoRun里,我們先begin,我把handler賦給了collection.handler,嗯簡單粗暴。并且把collection.now設(shè)為true,表示需要收集依賴了。
然后執(zhí)行handler(),就會到get里去執(zhí)行collect.startCollect。
當(dāng)startCollect的時候,開始干正經(jīng)活了,先判斷一下是不是now。前面我們劫持了getter,如果不判斷collection.now,那么collect.startCollect(oID + "" +key)總是會執(zhí)行。那就出大事情了。之后,咱們就可以放心的去收集handler了。
完事之后吧collection.now設(shè)為false。要不然你每每obj.a取值的時候都會反復(fù)的收集依賴。
好了,我想mobx的思路大概是這樣的。這是我的理解,有心的同學(xué)幫我糾糾錯,蟹蟹~
最后放上完整的本人的(cuo)dai照ma。
var globalID = 0 function observable(obj) { var oID = ++globalID return new Proxy(obj, { get: function (target, key, receiver) { collect.startCollect(oID + "" +key) return Reflect.get(target, key, receiver) }, set: function (target, key, value, receiver) { Reflect.set(target, key, value, receiver) collection[oID + "" + key] && collection[oID + "" + key].forEach(c => { c() }); } }) } var collection = {} var collect = { begin: function(handler) { collection.handler = handler collection.now = true }, startCollect: function(oIDKey) { if (collection.now) { if (collection[oIDKey]) { collection[oIDKey].push(collection.handler) } else { collection[oIDKey] = [collection.handler] } } }, end: function() { collection.now = false } } function autorun(handler) { collect.begin(handler) handler() collect.end() } var obj = observable({ a: 1, b: 2 }) autorun(() => { console.log("obj.a test1", obj.a) }) autorun(() => { console.log("obj.a test2", obj.a) })
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95299.html
摘要:原理分析的核心就是通過觀察某一個變量,當(dāng)該變量產(chǎn)生變化時,對應(yīng)的內(nèi)的回調(diào)函數(shù)就會發(fā)生變化?;卣{(diào)函數(shù)若依賴外部環(huán)境,則無法進行收集很好理解,的回調(diào)函數(shù)在預(yù)執(zhí)行的時候無法到達那一行代碼,所以收集不到。 Mobx解決的問題 傳統(tǒng)React使用的數(shù)據(jù)管理庫為Redux。Redux要解決的問題是統(tǒng)一數(shù)據(jù)流,數(shù)據(jù)流完全可控并可追蹤。要實現(xiàn)該目標,便需要進行相關(guān)的約束。Redux由此引出了dispa...
摘要:隨后,執(zhí)行官給出一張當(dāng)張三存款發(fā)生變化之時,此機構(gòu)的運作時序圖的確,小機構(gòu)靠人力運作,大機構(gòu)才靠制度運轉(zhuǎn)。第一條語句創(chuàng)建觀察員第一條語句張三我們調(diào)用的時候,就創(chuàng)建了對象,對象的所有屬性都將被拷貝至一個克隆對象并將克隆對象轉(zhuǎn)變成可觀察的。 ================前言=================== 初衷:網(wǎng)上已有很多關(guān)于 MobX 源碼解讀的文章,但大多閱讀成本甚高。...
摘要:建議將它們用于修改可觀察量或具有副作用的任何函數(shù)中。這意味著在一些定時器或者網(wǎng)絡(luò)請求,異步處理的情況下,它們的回調(diào)函數(shù)無法對狀態(tài)做成改變。這些回調(diào)函數(shù)都應(yīng)該有包裹,如果例子里面的一樣。 1. 介紹 1.1. 原理 React的render是 狀態(tài) 轉(zhuǎn)化為樹狀結(jié)構(gòu)的渲染組件的方法 而MobX提供了一種存儲,更新 狀態(tài) 的方法 React 和 MobX都在優(yōu)化著軟件開發(fā)中相同的問題。 ...
摘要:前言原本說接下來會專注學(xué)但是最新工作又學(xué)習(xí)了一些有意思的庫於是就再寫下來做個簡單的入門之前我寫過一篇文章這個也算是作為一個補充吧這次無非就是類似筆記把認為的一些關(guān)鍵點記下來有些地方還沒用到就衹是描述一下代碼有些自己寫的有些文檔寫的很好就搬下 前言 原本說接下來會專注學(xué)nodejs,但是最新工作又學(xué)習(xí)了一些有意思的庫,於是就再寫下來做個簡單的入門,之前我寫過一篇文章,這個也算是作為一個補...
摘要:有了這個,下一步就是開始對變化作出反應(yīng)。請注意,此延遲通知僅適用于當(dāng)前函數(shù)范圍中的。最快的方法是提供功能。只有當(dāng)返回的數(shù)據(jù)發(fā)生變化時,才會執(zhí)行副作用。最棒的部分是它會在運行后自動處理副作用。構(gòu)建可觀察數(shù)據(jù)掌握數(shù)據(jù)變更方法高階應(yīng)用實例 在上一部分中,我們研究了如何設(shè)置MobX狀態(tài)樹并使其可觀察。 有了這個,下一步就是開始對變化作出反應(yīng)。 坦率地說,這就是有趣的開始! MobX保證只要您的...
閱讀 5257·2021-10-15 09:42
閱讀 1621·2021-09-22 16:05
閱讀 3280·2021-09-22 15:57
閱讀 3418·2019-12-27 12:06
閱讀 978·2019-08-29 15:16
閱讀 2888·2019-08-26 12:24
閱讀 391·2019-08-26 12:02
閱讀 1897·2019-08-23 16:00