• 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]));
  • 相关阅读:
    JS截取文件后缀名
    百度地图API示例:使用vue添加删除覆盖物
    AttributeError: module 'tensorflow' has no attribute 'sub'
    ModuleNotFoundError: No module named 'numpy.core._multiarray_umath' ImportError: numpy.core.multiarray failed to import
    千锋很火的SpringBoot实战开发教程视频
    sublime text3 3176 注册码 License
    linux后台运行jar程序
    使用eclipse的SVN连接码云
    关于git上传文件的一个小问题
    js正则表达式,密码长度要大于6位,由数字和字母组成
  • 原文地址:https://www.cnblogs.com/liuyingde/p/13970358.html
Copyright © 2020-2023  润新知