可想實現一個本身的簡單jQuery庫?(十,實現on與off)

Lesson-9


關於事件部分,我思考了好久,也參考了許多,到底如何能用一個很簡單的方法實現如出一轍的on、off呢?javascript

最後個人設計思路是:java

1.有一個全局存儲全部Events的數組,存放每一個dom元素上的事件。git

2.給每一個DOM一個guid的惟一標識符,經過這個guid來找出Events數組裏的事件。github

因爲邏輯比較複雜,咱們先來畫個圖看看。segmentfault

事件設計流程圖

首先,咱們利用DOM能夠增長自定義屬性的原理,在它的身上存一個guid。數組

以後整個事件機制就根據這個guid來進行查找與存儲。less

接下來是代碼部分dom

Kodo.Events = []; //事件綁定存放的事件
Kodo.guid = 0; //事件綁定的惟一標識

on: function(type, selector, fn) {
    if (typeof selector == 'function') {
        fn = selector; //兩個參數的狀況
        for (var i = 0; i < this.length; i++) {
            if (!this[i].guid) {
                this[i].guid = ++Kodo.guid;
                //guid 不存在,給當前dom一個guid
    
                Kodo.Events[Kodo.guid] = {};
                /*
                *給Events[guid] 開闢一個新對象
                *用於存儲這個dom上的全部事件方法
                */
                
                Kodo.Events[Kodo.guid][type] = [fn]; //每一個方法都是一個數組
                //給這個新對象,賦予事件數組 "click" : [fn1,fn2,...]
    
                bind(this[i], type, this[i].guid);//綁定事件
    
            } else {//guid存在的狀況
                var id = this[i].guid;
                if (Kodo.Events[id][type]) {
                    //若是這存在是當前事件已經存過,不用在綁定事件,直接放入方法數組便可
                    Kodo.Events[id][type].push(fn);
                } else {
                    //這是存新事件,因此須要從新綁定一次
                    Kodo.Events[id][type] = [fn];
                    bind(this[i], type, id);
                }
            }
        }
    }
}

function bind(dom, type, guid) {
    dom.addEventListener(type, function(e) { //綁定相應事件
        for (var i = 0; i < Kodo.Events[guid][type].length; i++) {
            //循環執行那個方法數組便可
            Kodo.Events[guid][type][i].call(dom, e); //正確的dom回調
        }
    }, false);
}

因爲方法過長,我就把講解的都寫在了代碼裏,這樣看的也會更方便一些。ui

代碼仍是不夠形象!咱們來看看log就能更清晰明白其中的奧祕。this

經過控制檯log出f.Events 發現正是咱們想要的結果,每一個dom對應一個本身的evtObj, 經過Kodo.Events[guid] 能夠獲得指定的evtObj。而後便可取出本身相應的事件。

綁定事件demo

若是我繼續新增事件

綁定事件demo1

能夠發現,我只針對於第一個li增長了事件。log出Evnets也就只有第一個Object有新增,而且會增長到對應的事件數組裏。

理解了這個後要解除事件綁定,那就很是簡單了。一樣根據guid查找到對應的方法數組,delete便可

off: function(type, selector) {
    if (arguments.length == 0) {
        //若是沒傳參數,清空全部事件
        for (var i = 0; i < this.length; i++) {
            var id = this[i].guid;
            for (var j in Kodo.Events[id]) {
                delete Kodo.Events[id][j];
            }
        }
    } else if (arguments.length == 1) {
        //指定一個參數,則清空對應type的事件
        for (var i = 0; i < this.length; i++) {
            var id = this[i].guid;
            delete Kodo.Events[id][type];
        }
    } 
}

一個沒有帶有事件委託的on、off就能夠這樣實現了。

那若是咱們要實現帶委託的怎麼辦呢?

咱們能夠用這一樣的思路實現,只是要多進行一個指定selector的存儲。

這個咱們就放在下一課最後講解。

star是尊重做者知識果實最好的回報 :)

github地址: https://github.com/MeCKodo/forchange/tree/master/lesson-9
可想實現一個本身的簡單jQuery庫?(九):http://segmentfault.com/a/1190000004028768

相關文章
相關標籤/搜索