Event

浏览器Web的事件模型可分为两部分: 1. 监听事件的对象; 2. 分发的事件

1. 监听事件的对象: 基于 EventTarget 接口实现, 其负责事件的注册, 注销和派发

2. 分发的事件: 基于 Event 接口实现, 其负责创建出一个事件, 在需要派发事件的对象上广播该事件,广播可以被停止;

由此 , 便可构造出任意类型的事件, 在任意不同的对象上广播事件;

 

因为 Node,XMLHttpRequest 等对象都继承了 EventTarget 类, 所以可以在它们的实例上注册/注销/派发任意类型的事件

 

 

一个简易的 Event - EventTarget 事件模型实现

function MyEventTarget() {
    this.listeners = {}
}
MyEventTarget.prototype.addEventListener = function(type, callback, options) {
    if (this.listeners[type]) {
        this.listeners[type].push(callback)
    } else {
        this.listeners[type] = [callback]
    }
}
MyEventTarget.prototype.removeEventListener = function(type, callback) {
    var listeners, index;
    if (listeners = this.listeners[type]) {
        while (index = listeners.indexOf(callback) !== -1) {
            listeners.splice(index, 1)
        }
    }
}
MyEventTarget.prototype.dispatchEvent = function(event) {
    var type = event && event.type,
        listeners,
        callStack = event && event.path;
    
    if (callStack) {
        for(var i = 0; i < callStack.length; i++) {
            // 阻止了事件冒泡
            if (!event.bubbles) {
                break;
            }

            if (type && (listeners = callStack[i].listeners[type])) {
                for (var k = 0; k < listeners.length; k++) {
                    // 阻止了事件的继续派发
                    if (event.eventPhase === 0) {
                        // 停止派发
                    } else {
                        listeners[k].call(event.target, event)
                    }
                }
            }
        }
    } else {
        if (type && (listeners = this.listeners[type])) {
            for (var k = 0; k < listeners.length; k++) {
                if (event.eventPhase === 0) {
                    // 停止派发
                } else {
                    listeners[k].call(event.target, event)
                }
            }
        }
    }
}


var myEv1 = new MyEventTarget();

function fn1(e) { console.log('第一个 监听 1', e.data) }
function fn2(e) { 
    e.data += '555'
    console.log('第一个 监听 2', e.data); 
    // e.stopPropagation();
    // e.stopImmediatePropagation()
}
function fn3(e) { console.log('第一个 监听 3', e.data); }

myEv1.addEventListener('show', fn1)
myEv1.addEventListener('show', fn2);
myEv1.addEventListener('show', fn3)


var myEv2 = new MyEventTarget();

function pfn1(e) { console.log('第二个 监听 1', e.data); }

myEv2.addEventListener('show', pfn1)



function myEvent(type, data, path) {
    this.type = type
    this.eventPhase = 2
    this.bubbles = true
    this.data = data
    this.path = path
}


myEvent.prototype.stopImmediatePropagation = function() {
    this.eventPhase = 0;
}
myEvent.prototype.stopPropagation = function() {
    this.bubbles = false
}
myEv1.dispatchEvent(new myEvent('show', '你好', [myEv1, myEv2]));

 

posted @ 2021-09-06 23:07  芋头圆  阅读(299)  评论(0编辑  收藏  举报