zoukankan      html  css  js  c++  java
  • JavaScript使用自定义事件实现简单的模块化开发

      WEB前端最常见驱动方式就是事件了, 所有交互等等都是通过事件,前端的常见事件有:

    UI事件;
    焦点事件;
    鼠标事件;
    滚轮事件;
    文本事件;
    键盘事件;
    变动事件;
    

      现在网页上有一个输入框, 如果我们要对用户输入的字符串进行过滤, 或者是截获用户的输入进行处理的话, 我们要肿么办  

      同学们纷纷举手说:“老师,我知道,是使用添加事件“,

      老师也很欣慰地点了点头, 这群家伙真的是越来越聪明了,

      老师又问了”如果要取消用户的输入怎么办了“,

      坐在最前排眼睛最小的同学急忙说”ev.preventDefault(),ev.returnValue = false;"

      老师又说“不错啊,都学会抢答了啊, 我裤子都脱了, 你就答这个2?” 

      

      过了一秒钟, 又一位同学主动跑到黑板这边写了如下的代码:

    <!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事件,然后通过这个事件的回调对用户的输入进行处理";

      如果在事件里面的代码多了, 我们又可以把事件的代码单独取出来作为一个函数:

    <!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

  • 相关阅读:
    【CF1023D】Array Restoration(构造,线段树)
    【CF1020E】Sergey's problem(构造)
    【CF1020D】The hat(交互,二分)
    【CF1017F】The Neutral Zone(Bitset,埃氏筛)
    【CF1016F】Road Projects(贪心)
    【ZOJ4063】Tournament(构造)
    EQueue
    领域驱动设计(DDD)部分核心概念的个人理解
    DDD CQRS架构和传统架构的优缺点比较
    限流算法-三种思路
  • 原文地址:https://www.cnblogs.com/diligenceday/p/4235113.html
Copyright © 2011-2022 走看看