本日想簡樸聊聊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)
})