自定义事件--JS自定义一个事件(一)

来源:互联网 发布:骑马与砍杀 知乎 编辑:程序博客网 时间:2024/05/16 13:41

抽象→具象→本质→数据层
你有没有觉得这种行为表现有点类似于往长枪里面塞子弹(add),(扣动扳手 – click)发射的时候按照塞进去的顺序依次出来。这种行为表现为我们实现自定义事件提供了思路:我们可以定义一个数组,当添加事件的时候,我们push进去这个事件处理函数;当我们执行的时候,从头遍历这个数组中的每个事件处理函数,并执行。

当多个事件以及对应数据处理函数添加后,我们最终会得到一个类似下面数据结构的对象:

_listener = {    "click": [func1, func2],    "custom": [func3],    "defined": [func4, func5, func6]}

因此,如果我们脱离DOM, 纯碎在数据层面自定义事件的话,我们只要以构建、遍历和删除_listener对象为目的即可。

字面量实现

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) {        var arrayEvent = this._listeners[type];        if (typeof type === "string" && arrayEvent instanceof Array) {            if (typeof fn === "function") {                for (var i=0, length=arrayEvent.length; i<length; i+=1){                    if (arrayEvent[i] === fn){                        this._listeners[type].splice(i, 1);                        break;                    }                }            } else {                delete this._listeners[type];            }        }        return this;    }};

//------------- 以下为测试代码 -----------// 添加自定义事件var fnAlert1, fnAlert2;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");    }};

原型和构造函数实现方式

var EventTarget = function() {    this._listener = {};};EventTarget.prototype = {    constructor: this,    addEvent: function(type, fn) {        if (typeof type === "string" && typeof fn === "function") {            if (typeof this._listener[type] === "undefined") {                this._listener[type] = [fn];            } else {                this._listener[type].push(fn);                }        }        return this;    },    addEvents: function(obj) {        obj = typeof obj === "object"? obj : {};        var type;        for (type in obj) {            if ( type && typeof obj[type] === "function") {                this.addEvent(type, obj[type]);                }        }        return this;    },    fireEvent: function(type) {        if (type && this._listener[type]) {            var events = {                type: type,                target: this                };                        for (var length = this._listener[type].length, start=0; start<length; start+=1) {                this._listener[type][start].call(this, events);            }        }        return this;    },    fireEvents: function(array) {        if (array instanceof Array) {            for (var i=0, length = array.length; i<length; i+=1) {                this.fireEvent(array[i]);            }        }        return this;    },    removeEvent: function(type, key) {        var listeners = this._listener[type];        if (listeners instanceof Array) {            if (typeof key === "function") {                for (var i=0, length=listeners.length; i<length; i+=1){                    if (listeners[i] === listener){                        listeners.splice(i, 1);                        break;                    }                }            } else if (key instanceof Array) {                for (var lis=0, lenkey = key.length; lis<lenkey; lis+=1) {                    this.removeEvent(type, key[lenkey]);                }            } else {                delete this._listener[type];            }        }        return this;    },    removeEvents: function(params) {        if (params instanceof Array) {            for (var i=0, length = params.length; i<length; i+=1) {                this.removeEvent(params[i]);            }            } else if (typeof params === "object") {            for (var type in params) {                this.removeEvent(type, params[type]);                }        }        return this;        }};

//------------- 以下为测试代码 -----------var myEvents = new EventTarget();myEvents.addEvents({    "once": function() {        alert("该弹框只会出现一次!");            this.removeEvent("once");    },    "infinity": function() {        alert("每次点击页面,该弹框都会出现!");        }});document.onclick = function(e) {    e = e || window.event;    var target = e.target || e.srcElement;    if (!target || !/input|pre/i.test(target.tagName)) {        myEvents.fireEvents(["once", "infinity"]);    }};