谈谈JS的观察者模式(自定义事件)

来源:互联网 发布:ant构建 tomcat源码 编辑:程序博客网 时间:2024/06/05 20:47

观察者模式:
这是一种创建松散耦合代码的技术。它定义对象间 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。由主体和观察者组成,主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。主体并不知道观察者的任何事情,观察者知道主体并能注册事件的回调函数。

例子:

假如我们正在开发一个商城网站,网站里有header头部、nav导航、消息列表、购物车等模块。这几个模块的渲染有一个共同的前提条件,就是必须先用ajax异步请求获取用户的登录信息。这是很正常的,比如用户的名字和头像要显示在header模块里,而这两个字段都来自用户登录后返回的信息。这个时候,我们就可以把这几个模块的渲染事件都放到一个数组里面,然后待登录成功之后再遍历这个数组并且调用每一个方法。

function EventTarget(){         this.handlers = {}; } EventTarget.prototype = {         constructor: EventTarget,    addHandler: function(type, handler){         if (typeof this.handlers[type] == "undefined"){              this.handlers[type] = [];         }         this.handlers[type].push(handler);     },     fire: function(event){         if (!event.target){             event.target = this;         }         if (this.handlers[event.type] instanceof Array){             var handlers = this.handlers[event.type];             for (var i=0, len=handlers.length; i < len; i++){                 handlers[i](event);             }         }     },     removeHandler: function(type, handler){         if (this.handlers[type] instanceof Array){             var handlers = this.handlers[type];             for (var i=0, len=handlers.length; i < len; i++){                 if (handlers[i] === handler){                     break;                 }             }             handlers.splice(i, 1);           }      }};

大概意思就是,创建一个事件管理器。handles是一个存储事件处理函数的对象。

addHandle:是添加事件的方法,该方法接收两个参数,一个是要添加的事件的类型,一个是这个事件的回调函数名。调用的时候会首先遍历handles这个对象,看看这个类型的方法是否已经存在,如果已经存在则添加到该数组,如果不存在则先创建一个数组然后添加。

fire方法:是执行handles这个对象里面的某个类型的每一个方法。

removeHandle:是相应的删除函数的方法。

var Event = {    // 通过on接口监听事件eventName    // 如果事件eventName被触发,则执行callback回调函数    on: function (eventName, callback) {        //我的代码        if(!this.handles){             this.handles={};            }             if(!this.handles[eventName]){            this.handles[eventName]=[];       }       this.handles[eventName].push(callback);    },    // 触发事件 eventName    emit: function (eventName) {        //你的代码       if(this.handles[arguments[0]]){           for(var i=0;i<this.handles[arguments[0]].length;i++){               this.handles[arguments[0]][i](arguments[1]);           }       }    }};
var person1 = {};var person2 = {};Object.assign(person1, Event);Object.assign(person2, Event);person1.on('call1', function () {    console.log('person1');});person2.on('call2', function () {    console.log('person2');});person1.emit('call1'); // 输出 'person1'person1.emit('call2'); // 没有输出person2.emit('call1'); // 没有输出person2.emit('call2'); // 输出 'person2'

完整版

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Document</title>    <script src='./mapbox-gl.js'></script><link href='./mapbox-gl.css' rel='stylesheet' /><style>.pageCover            {                width:100%;                height:100%;                position:absolute;                z-index:10;                background-color:#666;                opacity:0.5;                display:block;            }</style></head><body>    <button id="button1">butn1</button>    <button id="button2">butn2</button>    <div class="pageCover"></div></body></html><script>    var Event = {    _listeners: {},        addEvent: function(type, fn) {        if (typeof this._listeners[type] === "undefined") {            this._listeners[type] = [];        }        if (typeof fn === "function") {            this._listeners[type].push(fn);        }            return this;    },    fireEvent: function(type) {        var arrayEvent = this._listeners[type];        if (arrayEvent instanceof Array) {            for (var i=0, length=arrayEvent.length; i<length; i+=1) {                if (typeof arrayEvent[i] === "function") {                    arrayEvent[i]({type: type});                    }            }        }            return this;    },    removeEvent: function(type, fn) {        if (typeof type === "string" && arrayEvent instanceof Array) {            if (typeof fn === "function") {                for (var i=0, length=this._listeners[type].length; i<length; i+=1){                    if (this._listeners[type][i] === fn){                        this._listeners[type].splice(i, 1);                        break;                    }                }            } else {                delete this._listeners[type];            }        }        return this;    }};    //test //  // 添加自定义事件Event.addEvent("alert", fnAlert1 = function() {    alert("第一个弹出!");}).addEvent("alert", fnAlert2 = function() {    alert("第二个弹出!");});// // 按钮绑定事件,用来清除自定义事件var elButton1 = document.getElementById("button1"),    elButton2 = document.getElementById("button2");elButton1.onclick = function() {    Event.removeEvent("alert");    alert("alert事件清除成功!");    // 此时后一个按钮卧底了,故隐藏    elButton2.style.display = "none";};elButton2.onclick = function() {    Event.removeEvent("alert", fnAlert1);    alert("第一个alert清除成功!");};// 点击文档,触发自定义事件document.onclick = function(e) {    e = e || window.event;    var target = e.target || e.srcElement;    // 如果文档点击元素标签名不是input    if (!target || !/input|pre/i.test(target.tagName)) {        Event.fireEvent("alert");    }};</script>
阅读全文
0 0
原创粉丝点击