小微型庫(3.繫結on和解綁off)

liangsheng0111發表於2018-11-05

on繫結

$("div").on("click mouseenter click.Liang", function(){});

off解綁

$("div").off();

$("div").off("click.sjl");

//對於_addEventFn(){}函式的解釋
//events屬性是以下的格式
    div.events = {
        click : {
            sjl : function(){
                console.log();
            },
            yl : function(){

            },
            anonymous : [fn, fn, fn]  //存放沒有自定義名字的事件函式值
        },
        mouseenter : {
            anonymous : [fn, fn, fn],
            sjl : function(){
                
            },
            yl : function(){
                
            }
        },
    }
複製程式碼
//阻止預設行為的相容
if(!Event.prototype.preventDefault){
    Event.prototype.preventDefault = function(){
        window.event.returnValue = false;
    };
}
//阻止冒泡的相容
if(!Event.prototype.stopPropagation){
    Event.prototype.stopPropagation = function{
        window.event.cancelBubble = true;
    };
}
//將新增到dom身上的事件函式儲存起來的方法
    function _addEventFn(data){
    //dom:節點  type:事件陣列  fn:事件函式
    //之前從來沒繫結過任何事件,把它變成一個物件
    if(typeof data.dom.events === "undefined"){
        data.dom.events = {};
    }
    //之前沒有繫結過相同型別的事件
    if(typeof data.dom.events[data.type[0]] === "undefined"){
        data.dom.events[data.type[0]] = {};
        data.dom.events[data.type[0]].anonymous = [];
        //anonymous是一個陣列,存放匿名函式
    }
    //type是陣列,類似["mouseenter", "sjl"] 或者["click"]
    //判斷有沒有自定義事件的名字  存事件函式
    if(data.type[1] === undefined){
        //如果為undefined,說明是匿名函式,存放到anonymous屬性對應的陣列中
        data.dom.events[data.type[0]].anonymous.push(data.fn);
    }else{
        data.dom.events[data.type[0]][data.type[1]] = data.fn;
        // data.dom.events[data.type[0]]代表事件 例如click
    }
    }

 //相容removeEventListener
    function _removeEvent(dom, type, fn, bool){
        //v, key1, v.events[key1].anonymous[j], false
        if(dom.removeEventListener){
            //主流
            dom.removeEventListener(type, fn, !!bool);
        }else{
            //ie
            dom.detachEvent("on"+type, fn);
        }
     }
//原型裡的方法
Liang.prototype = function(){
    constructor : Liang,
    init : function(){}, //(1)
    html : function(){}, //(2)
    //事件繫結
    on : function(eventType, fn){
        //非字串不做操作
        if(typeof eventType !== "string") return;
        var arr = eventType.trim().split(/\s+/);
        for(var i = 0, len = this.length; i < len; i++){
            (function(i, that){
               //that當前jq物件中的元素
                for(var j = 0, len = var.lenght; j < len; j++ ){
                    var type = arr[j].split(/\./),
                        eventFnName = null;
                    if(type[0] === "mousewheel"){
                        //需要判斷火狐及其他瀏覽器的事件
                        function _eventWheelFn(e){
                            var dir = e.wheelDelta / 120 || -e.detail / 3;
                            fn.call(that, e, dir) === false && e.preventDefault();
                        }
                        type[0] = (that.onmousewheel === null) ? "mousewheel" : "DOMMouseScroll";
                        eventFnName = _eventWheelFn;
                    }else{
                        function _eventFn(e){
                            e = e || window.event;
                            fn.call(that, e) === false && e.preventDefault;
                        }
                        eventFnName = _eventFn;
                    }
                    that.addEventListener ? 
                    that.addEventListener(type[0], eventFnName, false) :
                    that.attachEvent("on"+type[0], eventFnName);
                    
                    //儲存對應事件函式
                    _addEventFn({
                        dom : that,
                        type : type,
                        fn : eventFnName
                    });
                }
            }(i, this[i]))
        }
        return this;
    },
    //事件解綁
    off : function(){
        if(typeof eventType === "undefined"){
            //解綁所有事件
            Liang.each(this, function(v){
                // v 當前進來的元素
                for(var key1 in v.events){
                    // key1 是事件型別的名字 例如 click mouseenter
                    for(var key2 in v.events[key1]){
                        // key2 是事件型別物件中自定義的名字 例如 sjl
                        if(Liang.type(v.events[key1][key2]) === "function"){
                        //給自定義名字的事件解綁函式
                            _removeEvent(v, key1, v.events[key1][key2],false);
                        }else{
                            //給anonymous陣列中的函式解綁
                            var len = v.events[key1].anonymous.length;
                            for(var j = 0; j < len; j++){
                              //解綁anonymous陣列內的函式
                              _removeEvent(v, key1, v.events[key1].anonymous[j], false);
                            }
                        }
                    }
                }
                v.events = {}; //清空events裡所有資料
            });
        }else if(typeof eventType === "string"){ //例如 "click.yl mouseenter.sjl"
            var arr = eventType.trim().split(/\s+/); //["click.yl", "mouseenter.sjl"]
            //判斷輸入的為[""],則不作操作
            if(arr.toString() === "") return this;
            //對事件名陣列的遍歷
            for(var i = 0, len = arr.length; i < len; i++){
                var type = arr[i].split(/\./); //["click","yl"],["mouseenter","sjl"] 
                //遍歷例項物件,取到元素,解綁元素身上對應的事件
                Liang.each(this, function(v){
                    //判斷是否火狐,修改對應的事件名
                    if(type[0] === "mousewheel"){
                        //判斷滾動事件是否在火狐或者主流瀏覽器執行
                        type[0] = (v.onmousewheel === null) ? "mousewheel" : "DOMMouseScroll";
                    }
                    if(type.length > 1){
                        //解綁自定義名的事件函式
                        _removeEvent(v, type[0], v.events[type[0]][type[1]], false);
                        delete v.events[type[0]][type[1]];
                    }else{
                        //解綁同型別事件
                        //解綁對應事件的所有匿名事件 例如$("div").off("click")
                        for(var j = 0, len = v.events[type[0]].anonymous.length; j < len; j++){
                            _removeEvent(v, type[0], v.events[type[0]].anonymous[j], false);
                        }
                        //解綁該事件型別中有名的 例如$("div").off("click.yl")
                        for(var k in v.events[type[0]]){
                            // k是自定義屬性名 sjl yl  //判斷在不在陣列的原型上.false則表示不在,說明是function,取反
                            if(!(v.events[type[0]][k] instanceof Array)){
                                //自定義名字的事件屬性值
                                _removeEvent(v, type[0], v.events[type[0]][k], false);
                            }
                        }
                        delete v.events[type[0]];
                    }
                });
            }
        }
    },
 }

複製程式碼

相關文章