摘要:今天想簡單聊聊的和函數。的作用是使一個普通的對象,變得可觀察。下面來看看的簡單實現,這里不考慮對象的嵌套。一旦任何值發生了修改,就去執行傳入的方法。有點簡單粗暴,是不是。并且把設為,表示需要收集依賴了。
今天想簡單聊聊mobx的observable和autoRun函數。不了解es6的proxy和reflect的伙伴,需要先看看這方面的知識點。
1、observable
observable的作用是使一個普通的對象,變得可觀察。也就是說當一個對象變得可觀察了之后,當你改變對象里的一個值的時候,就會去觸發對應的有這個引用的autoRun函數。
下面來看看observable的簡單實現,這里不考慮對象的嵌套。就假設它只有一層。方便理解概念。
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 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這里表示由它來“代理”某些操作,可以譯為“代理器”。
這里用Proxy是因為當你在可觀察對象上加入新的屬性時,就不會像Object.defineProperty那樣新的屬性沒法監聽了。
像上面代碼那樣,咱們就成功的攔截了一個對象的getter和setter了。
每次當你obj.a或者obj.b的時候都會進入get方法。咱們在返回obj.a,之前都會去收集依賴。至于到底要不要收集依賴,我這里是由collect.startCollect去判斷的。
每當你obj.a = "balabala"的時候,咱們也攔截了set方法。在寫入值的之后,就要搞事情了,偷偷地去把收集來的依賴相應的依賴,給全部執行一遍(如果確實有的話)。
2、autoRun
一旦任何值發生了修改,就去執行傳入autoRun的方法。
function autorun(handler) { collect.begin(handler) handler() collect.end() }
有點簡單粗暴,是不是。開始收集依賴了,我先發個信號。然后把autoRun里的handler給執行一遍。最后,打聲招呼:小朋友你已經兌過獎了,回家吧。執行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設為true,表示需要收集依賴了。
然后執行handler(),就會到get里去執行collect.startCollect。
當startCollect的時候,開始干正經活了,先判斷一下是不是now。前面我們劫持了getter,如果不判斷collection.now,那么collect.startCollect(oID + "" +key)總是會執行。那就出大事情了。之后,咱們就可以放心的去收集handler了。
完事之后吧collection.now設為false。要不然你每每obj.a取值的時候都會反復的收集依賴。
好了,我想mobx的思路大概是這樣的。這是我的理解,有心的同學幫我糾糾錯,蟹蟹~
最后放上完整的本人的(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) })
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95299.html
摘要:原理分析的核心就是通過觀察某一個變量,當該變量產生變化時,對應的內的回調函數就會發生變化。回調函數若依賴外部環境,則無法進行收集很好理解,的回調函數在預執行的時候無法到達那一行代碼,所以收集不到。 Mobx解決的問題 傳統React使用的數據管理庫為Redux。Redux要解決的問題是統一數據流,數據流完全可控并可追蹤。要實現該目標,便需要進行相關的約束。Redux由此引出了dispa...
摘要:隨后,執行官給出一張當張三存款發生變化之時,此機構的運作時序圖的確,小機構靠人力運作,大機構才靠制度運轉。第一條語句創建觀察員第一條語句張三我們調用的時候,就創建了對象,對象的所有屬性都將被拷貝至一個克隆對象并將克隆對象轉變成可觀察的。 ================前言=================== 初衷:網上已有很多關于 MobX 源碼解讀的文章,但大多閱讀成本甚高。...
摘要:前言原本說接下來會專注學但是最新工作又學習了一些有意思的庫於是就再寫下來做個簡單的入門之前我寫過一篇文章這個也算是作為一個補充吧這次無非就是類似筆記把認為的一些關鍵點記下來有些地方還沒用到就衹是描述一下代碼有些自己寫的有些文檔寫的很好就搬下 前言 原本說接下來會專注學nodejs,但是最新工作又學習了一些有意思的庫,於是就再寫下來做個簡單的入門,之前我寫過一篇文章,這個也算是作為一個補...
摘要:有了這個,下一步就是開始對變化作出反應。請注意,此延遲通知僅適用于當前函數范圍中的。最快的方法是提供功能。只有當返回的數據發生變化時,才會執行副作用。最棒的部分是它會在運行后自動處理副作用。構建可觀察數據掌握數據變更方法高階應用實例 在上一部分中,我們研究了如何設置MobX狀態樹并使其可觀察。 有了這個,下一步就是開始對變化作出反應。 坦率地說,這就是有趣的開始! MobX保證只要您的...
閱讀 5222·2021-10-15 09:42
閱讀 1613·2021-09-22 16:05
閱讀 3272·2021-09-22 15:57
閱讀 3407·2019-12-27 12:06
閱讀 971·2019-08-29 15:16
閱讀 2884·2019-08-26 12:24
閱讀 387·2019-08-26 12:02
閱讀 1890·2019-08-23 16:00