どの牛も、子牛も自分の庫であるEvent処理をしなければならないと言われています.

29327 ワード

今日时间を割いて一部のEventの処理の方面の関数を书いてますますjQueryの优秀さを感じて、自分の前期の考えはあまりにも粗雑で、后ろのこれらの関数のパラメータが多くて、操作はとても直感的ではありませんて、见たところ再构筑するリズムで、幸いなことに小さい友达は慰めて、构造はすべて変えました.探し続けよう
ブラウザの互換性
Event処理のライブラリ関数を書く難点はブラウザの互換性の問題であり、IEの低バージョンブラウザではイベントオブジェクトが常にwindowにある.eventプロパティでは、他のブラウザでeventがイベントハンドラの最初のパラメータとして渡されます.またEventオブジェクトの属性やメソッドにも多くの違いがあり,JavaScriptとHTMLのインタラクション-イベントではほぼまとめられているが,イベントハンドラバインドに関する違いを写した.
1.パラメータの個数が異なり、この最も直感的で、addEventListenerには3つのパラメータがあり、attachEventは2つしかなく、attachEventが追加したイベントハンドラはバブル段階でしか発生しない.addEventListenerの3番目のパラメータは、追加されたイベントハンドラがキャプチャフェーズで処理されるか、バブルフェーズで処理されるかを決定します(一般的にブラウザ互換性のためにバブルフェーズに設定されています).
2.最初のパラメータの意味が異なり、addEventListenerの最初のパラメータはイベントタイプ(例えばclick,load)であり、attachEventの最初のパラメータはイベント処理関数名(onclick,onload)を示す
3.イベントハンドラの役割ドメインが異なり、addEventListenerの役割ドメインは要素そのものであり、thisはトリガ要素を指し、attachEventイベントハンドラはグローバル変数内で実行され、thisはwindowである
4.1つのイベントに複数のイベントハンドラを追加する場合、実行順が異なりaddEventListener追加は追加順に実行されるが、attachEventが複数のイベントハンドラを追加する場合は順序が不規則(追加方法が少ない場合は追加順の逆順に実行されることが多いが、追加が多いと不規則になる)であるため、複数追加する場合、実行順序に依存しないほうがいいです.関数の実行順序に依存する場合は、ブラウザを期待しないで自分で処理したほうがいいです.
最も簡単な4つ
まず4つ書くのが一番簡単です
  • getEvent:イベントオブジェクトを取得
  • getTarget:イベントソースオブジェクトを取得
  • preventDefault:イベントのデフォルト動作をブロック
  • stopPropagation:イベントの発泡を阻止する
  •  
    (function (window) {
                var ssLib = {
                    getEvent: function (e) {
                        return e ? e : window.event;
                    },
    
                    getTarget: function (e) {
                        var e = this.getEvent(e);
                        return e.target || e.srcElement;
                    },
    
                    preventDefault: function (e) {
                        var e = this.getEvent(e);
                        if (e.preventDefault) {
                            e.preventDefault();
                        } else {
                            e.returnValue = false;
                        }
                    },
    
                    stopPropagation: function (e) {
                        var e = this.getEvent(e);
                        if (e.stopPropagation) {
                            e.stopPropagation();
                        } else {
                            e.cancelBubble = true;
                        }
                    }
                };
                window.ssLib = window.ss = ssLib;
            })(window);

    コードは簡単で、頭のいい仲間たちが見ればわかると信じて、あまり説明しません.
    addEvent/removeEvent
  • addEvent:要素バインドイベントハンドラ
  • removeEvent:要素イベントハンドラ
  • を削除
    addEvent: function (element, type, handler, key) {
                        var key = key || handler;
                        if (element[type + key])
                            return false;
                        if (typeof element.addEventListener != "undefined") {
                            element[type + key] = handler;
                            element.addEventListener(type, handler, false);
                        }
                        else {
                            element['e' + type + key] = handler;
                            element[type + key] = function () {
                                element['e' + type + key](window.event);
                            };
                            element.attachEvent('on' + type, element[type + key]);
                        }
                        return true;
                    },
    
                    removeEvent: function (element, type, key) {
                        if (!element[type + key])
                            return false;
    
                        if (typeof element.removeEventListener != "undefined") {
                            element.removeEventListener(type, element[type + key], false);
                        }
                        else {
                            element.detachEvent("on" + type, element[type + key]);
                            element['e' + type + key] = null;
                        }
    
                        element[type + key] = null;
                        return true;
                    },

    この2つの関数の互換性の書き方はたくさんあって、多くの牛の書き方を結合した後に私が使った上のバージョン、このようにするのは複雑に見えますが、実際には主に上述した、複数のイベントハンドラの実行順序の問題を除いたブラウザの互換性の問題を解決して、比較的に分かりにくいIEバインド部分はthisを処理するために書いたのです.
    使用時には、内部識別バインド関数としてキーが入力され、バインドされていない場合はhandler自体がキーとして使用されるため、このように使用できます.
    ssLib.addEvent(element,'click',function(){},'test');
            ssLib.removeEvent(element,'click','test');
            
            function handler(){}
            
            ssLib.addEvent(element,'click',handler);
            ssLib.removeEvent(element,'click',handler);

    on/off
    これはjQueryのon/delegateとYUIのdelegateを見て芽生えたアイデアですが、普段は人のことを自分で書いたことがないので、急いで1つ書いて、感慨深いですが、やはりjQueryが使いやすいです
    on: function (parent, type, handler,validater,key) {
                        var _key=key || handler;
                        parent['on'+type+_key]=function (e) {
                            var target = ssLib.getTarget(e);
                            var isFire = validater(target);
                            if (isFire) {
                                target[type + _key] = handler;
                                target[type + _key](e);
                            }
                        };
                        
                        ssLib.addEvent(parent, type,parent['on'+type+_key] , key);
                    },
    
                    off: function (parent, type, key) {
                        if(typeof key=='function'){
                            ssLib.removeEvent(parent, type, parent['on'+type+key]);
                        }else{
                            ssLib.removeEvent(parent, type, key);
                        }
                        parent['on'+type+key]=null;
                    }

    書き方はさっきと似ていて、ぐるぐる回るのもこの問題を解決するためで、このように使うことができます
    <div id="test">
            <div id="t1">T1</div>
            <div id="t2">T2</div>
        </div>

     
    var parent = document.getElementById('test');
            
            var handler=function () {
                alert(this.id);
            }
            
            var validater=function (obj) {
                if(obj.parentNode.id=='test'){
                    return true;
                }else{
                    return false;
                }
            }
            
            ss.on(parent, 'click', handler, validater);
            
            ss.off(parent,'click',handler);
            
            ss.on(parent, 'click', handler, validater,'delegate');
            
            ss.off(parent,'click','delegate');

    ready
    jQueryを使ったことがある人はきっとこの関数を知っていて、自分のライブラリを書く時はいろいろとうらやましくて、そこで自分のライブラリに加えました
    ready: function (fn) {
                        if (document.addEventListener) {
                            document.addEventListener("DOMContentLoaded", function () {
                                document.removeEventListener("DOMContentLoaded", arguments.callee, false);//       
                                fn();
                            }, false);
                        } else if (document.addEvent) {
                            var doc = window.document, done = false;
                            // only fire once
                            var init = function () {
                                if (!done) {
                                    done = true;
                                    fn();
                                }
                            };
                            // polling for no errors
                            (function () {
                                try {
                                    // throws errors until after ondocumentready
                                    doc.documentElement.doScroll('left');//             
                                } catch (e) {
                                    setTimeout(arguments.callee, 50);
                                    return;
                                }
                                // no errors, fire
                                init();
                            })();
                            // trying to always fire before onload
                            doc.onreadystatechange = function () {
                                if (doc.readyState == 'complete') {
                                    doc.onreadystatechange = null;
                                    init();
                                }
                            };
                        }
                    }

    上のコードを理解するにはAn alternative for DOMContentLoaded on Internet Explorerを見たほうがいいです.
    現代ブラウザではドキュメントのロードが完了すると「DOMContentLoaded」イベントがトリガーされ、下位バージョンIEではドキュメントのロードが完了するとdoScrollメソッドが有効になります
    Event部分ソースコード
    (function (window) {
                var ssLib = {
                    getEvent: function (e) {
                        return e ? e : window.event;
                    },
    
                    getTarget: function (e) {
                        var e = this.getEvent(e);
                        return e.target || e.srcElement;
                    },
    
                    preventDefault: function (e) {
                        var e = this.getEvent(e);
                        if (e.preventDefault) {
                            e.preventDefault();
                        } else {
                            e.returnValue = false;
                        }
                    },
    
                    stopPropagation: function (e) {
                        var e = this.getEvent(e);
                        if (e.stopPropagation) {
                            e.stopPropagation();
                        } else {
                            e.cancelBubble = true;
                        }
                    },
    
                    addEvent: function (element, type, handler, key) {
                        var key = key || handler;
                        if (element[type + key])
                            return false;
                        if (typeof element.addEventListener != "undefined") {
                            element[type + key] = handler;
                            element.addEventListener(type, handler, false);
                        }
                        else {
                            element['e' + type + key] = handler;
                            element[type + key] = function () {
                                element['e' + type + key](window.event);
                            };
                            element.attachEvent('on' + type, element[type + key]);
                        }
                        return true;
                    },
    
                    removeEvent: function (element, type, key) {
                        if (!element[type + key])
                            return false;
    
                        if (typeof element.removeEventListener != "undefined") {
                            element.removeEventListener(type, element[type + key], false);
                        }
                        else {
                            element.detachEvent("on" + type, element[type + key]);
                            element['e' + type + key] = null;
                        }
    
                        element[type + key] = null;
                        return true;
                    },
    
                    ready: function (fn) {
                        if (document.addEventListener) {
                            document.addEventListener("DOMContentLoaded", function () {
                                document.removeEventListener("DOMContentLoaded", arguments.callee, false);
                                fn();
                            }, false);
                        } else if (document.attachEvent) {
                            var doc = window.document, done = false;
                            // only fire once
                            var init = function () {
                                if (!done) {
                                    done = true;
                                    fn();
                                }
                            };
                            // polling for no errors
                            (function () {
                                try {
                                    // throws errors until after ondocumentready
                                    doc.documentElement.doScroll('left');
                                } catch (e) {
                                    setTimeout(arguments.callee, 50);
                                    return;
                                }
                                // no errors, fire
                                init();
                            })();
                            // trying to always fire before onload
                            doc.onreadystatechange = function () {
                                if (doc.readyState == 'complete') {
                                    doc.onreadystatechange = null;
                                    init();
                                }
                            };
                        }
                    },
    
                    on: function (parent, type, handler, validater, key) {
                        var _key = key || handler;
                        parent['on' + type + _key] = function (e) {
                            var target = ssLib.getTarget(e);
                            var isFire = validater(target);
                            if (isFire) {
                                target[type + _key] = handler;
                                target[type + _key](e);
                            }
                        };
    
                        ssLib.addEvent(parent, type, parent['on' + type + _key], key);
                    },
    
                    off: function (parent, type, key) {
                        if (typeof key == 'function') {
                            ssLib.removeEvent(parent, type, parent['on' + type + key]);
                        } else {
                            ssLib.removeEvent(parent, type, key);
                        }
                        parent['on' + type + key] = null;
                    }
                };
                window.ssLib = window.ss = ssLib;
            })(window);