【Vue原理】Event - 源碼版 之 自定義事件

寫文章不容易,點個讚唄兄弟 專一 Vue 源碼分享,文章分爲白話版和 源碼版,白話版助於理解工做原理,源碼版助於瞭解內部詳情,讓咱們一塊兒學習吧 研究基於 Vue版本 【2.5.17】app

若是你以爲排版難看,請點擊 下面連接 或者 拉到 下面關注公衆號也能夠吧dom

【Vue原理】Event - 源碼版 之 自定義事件 異步

Vue 的自定義事件很簡單,就是使用 觀察者模式 進行事件的監聽和分發函數

Vue 封裝的這個觀察者模式,能夠說是很完善了,這個能夠獨立抽取出來的在其餘項目中使用的代碼,只須要作一點點改動,把事件存儲器換個地方(Vue 放在了實例上)學習

我常常在項目中使用,就是爲了解耦或者解決一些異步的問題this

今天來詳細探索 Vue 的 自定義事件prototype

首先,Vue 的事件存儲器放在那裏?3d

沒錯,放在 vm._events 中code

你看,好比你這樣監聽事件blog

公衆號

看到實例上保存了你的事件 公衆號


一、事件存儲器

vm._events

看下這個事件存儲器在哪裏生成的

首先,實例在初始化的時候,給實例增長一個事件存儲器 _events

Vue.prototype._init = function(options) {

    initEvents(vm);    

    //...初始化選項數據,解析模板,掛載dom等

}

function initEvents(vm) {
    vm._events = Object.create(null);
}

之後,全部這個實例監聽的事件,就都存在這裏了

那麼,接下來就來看 自定義事件的源碼了

下面的源碼比較不太屬於 Vue 的內容,比較獨立,很實用,相信你們也都看得懂,這裏主要起一個記錄的做用

下面會有四個函數

綁定事件,$on

一次性綁定事件,$once

觸發事件,$emit

解綁事件,$off


二、$on

註冊事件,接收 事件名和回調,很清楚了,都能看得懂

Vue.prototype.$on = function(event, fn) {    

    var vm = this;   

    if (Array.isArray(event)) {        

        for (var i = 0,l = event.length; i < l; i++) {            
            this.$on(event[i], fn);
        }
    } 
    else { 
        (vm._events[event] || (vm._events[event] = [])).push(fn);

    }    

    // 爲了鏈式調用
    return vm
};

三、$once

單次註冊。只監聽一次,觸發以後立刻銷燬

它妙就妙在,把回調包裝了一下,在 回調執行時,先解綁事件,再調用原回調

Vue.prototype.$once = function(event, fn) {  

    var vm = this;     

    function on() {

        vm.$off(event, on);
        fn.apply(vm, arguments);
    }

    on.fn = fn;
    vm.$on(event, on);      

   
    // 爲了鏈式調用
    return vm
};

四、$emit

觸發事件,接收事件名,而後拿到本來設置的回調,遍歷調用

Vue.prototype.$emit = function(event) {  

    var vm = this;    

    var _events= event.toLowerCase();    

    var cbs = vm._events[_events]; 

    if (cbs) {

        cbs = cbs.length > 1 ? toArray(cbs) : cbs;        
        var args = toArray(arguments, 1);        

        for (var i = 0, l = cbs.length; i < l; i++) {

          cbs[i].apply(vm, args);
        }

    }    

    // 爲了鏈式調用
    return vm
};

五、$off

取消監聽事件或者移除監聽回調

接收事件名 和 綁定時的事件回調

很簡單的啦

Vue.prototype.$off = function(event, fn) {   

    var vm = this;    

    if (!arguments.length) {

        vm._events = Object.create(null);        

        return vm
    }    

    // 遞歸調用
    if (Array.isArray(event)) {        

        for (var i = 0, l = event.length; i < l; i++) { 
           this.$off(event[i], fn);
        }        
        return vm
    } 

    var cbs = vm._events[event];    

    if (!cbs) return vm    

    if (!fn) {

        vm._events[event] = null;        

        return vm

    }    

    // 去掉特定的函數
    if (fn) {        

        var cb;        

        var len = cbs.length;     

        // 遍歷移除相應回調
        while (len--) {

            cb = cbs[len];            

            if (cb === fn || cb.fn === fn) {

                cbs.splice(len, 1);                

                break

            }
        }
    }    

    // 爲了鏈式調用
    return vm
};

公衆號

相關文章
相關標籤/搜索