JavaScript使用自定義事件實現簡單的模塊化開發

原文: JavaScript使用自定義事件實現簡單的模塊化開發

  WEB前端最多見驅動方式就是事件了, 全部交互等等都是經過事件,前端的常見事件有:html

UI事件;
焦點事件;
鼠標事件;
滾輪事件;
文本事件;
鍵盤事件;
變更事件;

  如今網頁上有一個輸入框, 若是咱們要對用戶輸入的字符串進行過濾, 或者是截獲用戶的輸入進行處理的話, 咱們要腫麼辦  前端

  同窗們紛紛舉手說:「老師,我知道,是使用添加事件「,設計模式

  老師也很欣慰地點了點頭, 這羣傢伙真的是愈來愈聰明瞭,app

  老師又問了」若是要取消用戶的輸入怎麼辦了「,模塊化

  坐在最前排眼睛最小的同窗急忙說」ev.preventDefault(),ev.returnValue = false;"函數

  老師又說「不錯啊,都學會搶答了啊, 我褲子都脫了, 你就答這個2?」 post

  

  過了一秒鐘, 又一位同窗主動跑到黑板這邊寫了以下的代碼:ui

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MAKER</title>
</head>
<body>
    <div id="log">
        Log:
    </div>
    <input id="text">data</input>

    <script>
        window.onload = init;
        
        if(console&&console.log) {
            var originalLog = console.log;
            var log = document.getElementById("log");
            console.log = function(arg) {
                var eDiv = document.createElement("div");
                eDiv.innerHTML = typeof arg === "string" ? arg : arg.toString();
                log.appendChild( eDiv );
                originalLog.apply(console, arguments);
            };
        };

        function init () {
            var eText = document.getElementById("text");
            eText.addEventListener("keypress", function( ev ) {
                //邏輯所有在這裏面, 很簡單吧;
                var code = ev.which = ev.which || ev.keyCode || ev.charCode;
                console.log( code );
                if(code > 80) {
                    console.log("code>80");
                };
                if(ev.shiftKey === true) {
                    console.log("shift key is pressed!")
                }
            });
        };
    </script>
</body>
</html>

  "哎喲,不錯哦,這個*x"老師說道:"這個就是咱們最經常使用的方法, 直接爲元素綁定了keypress事件,而後經過這個事件的回調對用戶的輸入進行處理";this

  若是在事件裏面的代碼多了, 咱們又能夠把事件的代碼單獨取出來做爲一個函數:url

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MAKER</title>
</head>
<body>
    <div id="log">
        Log:
    </div>
    <input id="text">data</input>

    <script>
        window.onload = init;
        
        if(console&&console.log) {
            var originalLog = console.log;
            var log = document.getElementById("log");
            console.log = function(arg) {
                var eDiv = document.createElement("div");
                eDiv.innerHTML = typeof arg === "string" ? arg : arg.toString();
                log.appendChild( eDiv );
                originalLog.apply(console, arguments);
            };
        };
        var 我是事件 = function(ev) {
            //邏輯所有在這裏面, 很簡單吧;
            var code = ev.which = ev.which || ev.keyCode || ev.charCode;
            console.log( code );
            if(code > 80) {
                console.log("code>80");
            };
            if(ev.shiftKey === true) {
                console.log("shift key is pressed!")
            };
        };
        function init () {
            var eText = document.getElementById("text");
            eText.addEventListener("keypress", function( ev ) {
                我是事件(ev);
            });
        };
    </script>
</body>
</html>

  看起來清楚多了是吧, 可是在大的項目中(我說的是若是哇), 咱們想要充分解耦代碼, 能夠事件裏面的代碼所有從新分開:

  函數1 :console.log( code );

  函數2: 

  if(code > 80) {

      console.log("code>80");

 };
 函數3: 
 if(ev.shiftKey === true) {    console.log("shift key is pressed!")  };
 好吧,如今問題來了....
 
 如今有要上菜了哇, JS中的自定義事件, 充分利用JS的事件機制
 
抄自百科:對於自定義事件最須要了解的一點是,您的代碼必須致使這些事件發生。這些事件不會爲響應用戶或系統的動做而自動發生,即便可以編寫致使事件確實以這種方式發生的代碼也不例外。包含自定義事件的類模塊還必須包括一個喚起事件的公有方法。這個方法經過調用 RaiseEvent 語句並傳入爲事件定義的任何參數來喚起事件。這些參數按順序傳入爲響應事件而運行的事件過程當中
 
自定義事件就是一種的設計模式,好比訂閱者發佈者模式, 觀察者模式等等, 都是自定義事件基礎上的模式(我的觀點, 勿拍磚), 關鍵是不少大神寫代碼喜歡用這一種模式寫, 那麼咱們也能夠借鑑, 這樣就夠了;
 咱們如今把上面那段經過自定義事件的方式寫出來:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>MAKER</title>
</head>
<body>
    <script>
        //d爲目標對象, b爲一個函數對象;
        var __extends = this.__extends || function (d, b) {
            //繼承了靜態屬性
            for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            function __() { this.constructor = d; }
            //繼承了原型
            __.prototype = b.prototype;
            d.prototype = new __();
        };

        var EventEmitter = (function () {
            function EventEmitter() {
                this._events = {};
            }
            EventEmitter.prototype.emit = function (type) {
                var _this = this;
                var args = [];
                for (var _i = 0; _i < (arguments.length - 1); _i++) {
                    args[_i] = arguments[_i + 1];
                }
                // If there is no 'error' event listener then throw.
                if (type === 'error') {
                    if (!this._events[type] || (Array.isArray(this._events[type]) && !this._events[type].length)) {
                        if (args[0] instanceof Error) {
                            throw args[0];
                        } else {
                            throw new Error("Uncaught, unspecified 'error' event.");
                        }
                        return false;
                    }
                }
                if (this._events[type]) {
                    this._events[type].forEach(function (handler) {
                        return handler.apply(_this, args);
                    });
                    return true;
                }
                return false;
            };

            EventEmitter.prototype.addListener = function (type, listener) {
                if ('function' !== typeof listener) {
                    throw new Error('addListener only takes instances of Function');
                }
                var events = this._events;
                var listeners = events[type];
                if (!listeners)
                    listeners = events[type] = [];
                else if (listeners.indexOf(listener) >= 0)
                    return this;
                listeners.push(listener);
                return this;
            };

            EventEmitter.prototype.removeListener = function (type, listener) {
                var events = this._events;
                if (!events[type])
                    return this;
                var listeners = events[type];
                var i = listeners.indexOf(listener);
                if (i >= 0)
                    listeners.splice(i, 1);
                return this;
            };
            return EventEmitter;
        })();

    //寫一個小的案例, 爲了充分解耦代碼, 咱們能夠把代碼經過自定義的事件分紅幾個模塊;

    </script>

    <input id="text">data</input>

    <script>
        window.onload = init;
        function init () {
            var TextEvent = (function(Emiter) {
                __extends(TextEvent, Emiter);
                function TextEvent() {
                    Emiter.apply(this);
                };
                return TextEvent;
            }.call(TextEvent,EventEmitter));

            //建立了這個實例;
            var textEvent = new TextEvent();

            //爲實例添加自定義事件;
            textEvent.addListener("keypress", function preventDefault(ev) {
                ev.preventDefault();
            });
            //爲實例添加自定義事件;
            textEvent.addListener("keypress", function(ev) {
                var code = ev.which = ev.which || ev.keyCode || ev.charCode;
                console.log( code );
            });
            //爲實例添加自定義事件;
            textEvent.addListener("keypress", function(ev) {
                var code = ev.which = ev.which || ev.keyCode || ev.charCode;
                if(code > 80) {
                    console.log("code>80");
                };
            });
            //爲實例添加自定義事件;
            textEvent.addListener("keypress", function(ev) {
                var code = ev.which = ev.which || ev.keyCode || ev.charCode;
                if(ev.shiftKey === true) {
                    console.log("shift key is pressed!")
                };
            });

            document.getElementById("text").addEventListener("keypress", function( ev ) {
                textEvent.emit("keypress",ev)
            });
        };
    </script>
</body>
</html>

  樓主你他媽在逗我? 這麼多

 實現要懂JS的繼承:
        //d爲目標對象, b爲一個函數對象;
        var __extends = this.__extends || function (d, b) {
            //繼承了靜態屬性
            for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            function __() { this.constructor = d; }
            //繼承了原型
            __.prototype = b.prototype;
            d.prototype = new __();
        };

  其次呢, 自定義事件的代碼要懂, 不少地方都有用到;

        var EventEmitter = (function () {
            function EventEmitter() {
                this._events = {};
            }
            EventEmitter.prototype.emit = function (type) {
                var _this = this;
                var args = [];
                for (var _i = 0; _i < (arguments.length - 1); _i++) {
                    args[_i] = arguments[_i + 1];
                }
                // If there is no 'error' event listener then throw.
                if (type === 'error') {
                    if (!this._events[type] || (Array.isArray(this._events[type]) && !this._events[type].length)) {
                        if (args[0] instanceof Error) {
                            throw args[0];
                        } else {
                            throw new Error("Uncaught, unspecified 'error' event.");
                        }
                        return false;
                    }
                }
                if (this._events[type]) {
                    this._events[type].forEach(function (handler) {
                        return handler.apply(_this, args);
                    });
                    return true;
                }
                return false;
            };

            EventEmitter.prototype.addListener = function (type, listener) {
                if ('function' !== typeof listener) {
                    throw new Error('addListener only takes instances of Function');
                }
                var events = this._events;
                var listeners = events[type];
                if (!listeners)
                    listeners = events[type] = [];
                else if (listeners.indexOf(listener) >= 0)
                    return this;
                listeners.push(listener);
                return this;
            };

            EventEmitter.prototype.removeListener = function (type, listener) {
                var events = this._events;
                if (!events[type])
                    return this;
                var listeners = events[type];
                var i = listeners.indexOf(listener);
                if (i >= 0)
                    listeners.splice(i, 1);
                return this;
            };
            return EventEmitter;
        })();

 

  最後經過組合繼承, 實現了一個自定義事件類方法:

            var TextEvent = (function(Emiter) {
                __extends(TextEvent, Emiter);
                function TextEvent() {
                    Emiter.apply(this);
                };
                return TextEvent;
            }.call(TextEvent,EventEmitter));

  

  咱們經過實例化TextEvent, 爲這個實例添加自定義的方法;

  在onkeypress的事件回調觸發自定義事件textEvent.emit("keypress",ev), 最後的最後只要爲textEvent綁定自定義事件便可,這樣作的優點就是: 咱們能夠經過removeListener去除事件, 事件函數也能夠直接複用, 很靈活;


 

D

相關文章
相關標籤/搜索