事件是一种叫做观察者的设计模式,这是一种创建松散耦合的技术。观察者模式由两类对象组成:主体和观察者。主体负责发布事件。同时观察者通过订阅这些事件来观察该主体。该模式的一个关键概念是主体并不知道观察者的任何事情,也就是说它可以独自存在并正常运作即使观察者不存在。从另一方面来说。观察者知道主体并能注册事件的回调函数(事件处理程序),涉及到Dom上时,Dom元素便是主体,你的事件处理代码便是观察者。

事件是与Dom交互的最常见的方式,但它们也可以用于非Dom代码中--通过实现自定义事件。

自定义事件背后的概念是创建一个管理事件的对象。让其他对象监听那些事件。实现此功能的基本模式可以定义如下:

    function EventTarget(name1) {
        this.name = name1;
        this.handlers = {}
    }
    EventTarget.prototype = {
        constructor: EventTarget,
        addHandler: function(type, handler) {
            console.log(type);
            //刚开始只有type并没有为this.handlers[type]赋值
            if (typeof this.handlers[type] == "undefined") {
                this.handlers[type] = [];
                console.log("hi")
            }
            //接着执行push
            this.handlers[type].push(handler);
            console.log(this.handlers[type]);

        },
        fire: function(event) {
            if (!event.target) {
                event.target = this;
                console.log("not have eventTarget")
            }
            if (this.handlers[event.type] instanceof Array) {
                console.log("isArray")
                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);
            }
            console.log(handlers);
        }
    }

然后使用EventTarget类型的自定义事件:

	   function handleMessage(event) {
	     alert("Message received:" + event.message);
	   }
	   //创建一个新对象
	   var target = new EventTarget()

	   //添加一个事件处理程序
	   target.addHandler("message",handleMessage)

	   //触发事件
	   target.fire({type:"message",message:"Hello World"})

	   //删除事件处理程序
	   target.removeHandler("message",handleMessage);

	    //触发事件不会执行
	   target.fire({type:"message",message:"Hello Worldmmm"})

在这段代码中,定义了handleMessage()函数用于处理message事件。它接受event对象并输出message属性。调用target对象的addHandler()方法并传给"message"以及hadleMessage()函数。在接下来的一行,调用了fire()函数,并传给了2个属性,即type和message的对象。然后删除了事件处理程序,这样即使事件再次出发,也不会显示任何警告框。

因为这种功能是封装在一种自定义类型中的,其它对象可以继承EventTarget并获得这个行为

    function Person(name) {
        this.name = name;
        this.etarget = new EventTarget(this.name)
    }

    Person.prototype = {
        constructor: Person,
        addMessage: function(type, fn) {
            this.etarget.addHandler(type, fn)
        },
        say: function(message) {
            this.etarget.fire({ type: "message", message: message })
            console.log(this.name)
        }
    }

    function handleMessage(event) {
        console.log(event)
        //弹出NICHOLAS--SAYS:hi there
        alert(event.target.name + "---says:" + event.message);
    }

    //创建新Person实例
    var person = new Person("NICHOLAS");
    person.addMessage("message", handleMessage);
    person.say("hi there")
04-01 18:52