簡樸講講mobx的observable和autoRun

本日想簡樸聊聊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)
})
    原文作者:Runnnnn
    原文地址: https://segmentfault.com/a/1190000015049571
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞