事件委托

事件委托

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
    <title></title>
</head>
<body>
    <ul id="myLinks">
        <li id="goSomewhere">Go somewhere</li>
        <li id="doSomething">Do something</li>
        <li id="sayHi">Say hi</li>
    </ul>
    <script type="text/javascript">
    window.onload= function() {
        var list = document.getElementById("myLinks");
        addHandler(list, "click", function(ev) {
            var oEvent = ev||event;
            var target = getTarget(oEvent);
            switch(target.id) {
                case "doSomething":
                    document.title = "I changed the document's title";
                    break;

                case "goSomewhere":
                    location.href = "http://www.baidu.com";
                    break;

                case "sayHi":
                    alert("hi");
                    break;
            }
        })
    }
    function getTarget(event)
    {
        return event.target || event.srcElement;
    }
    function addHandler(element, type, handler)
    {
        if(element.addEventListener)
        {
            element.addEventListener(type, handler, false);//IE9、ff、sa、op、ch
        }else if (element.attachEvent)
        {
            element.attachEvent("on" + type, handler);//IE、op
        }else
        {
            element["on" + type] = handle;
        }
    }
    </script>
</body>
</html>

委托(代理)事件是那些被绑定到父级元素的事件,但是只有当满足一定匹配条件时才会被挪。这是靠事件的冒泡机制来实现的,

优点是:

(1)可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒

(2)可以实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适

缺点是:

事件代理的应用常用应该仅限于上述需求下,如果把所有事件都用代理就可能会出现事件误判,即本不应用触发事件的被绑上了事件。


实现事件模型bind与trigger

大致实现思路就是创建一个类或是匿名函数,在bind和trigger函数外层作用域创建一个字典对象,用于存储注册的事件及响应函数列表,bind时,如果字典没有则创建一个,key是事件名称,value是数组,里面放着当前注册的响应函数,如果字段中有,那么就直接push到数组即可。trigger时调出来依次触发事件响应函数即可。
  

function Emitter() {
    this._listener = [];
    //_listener[自定义的事件名] = [所用执行的匿名函数1, 所用执行的匿名函数2]
}

//注册事件
Emitter.prototype.bind = function(eventName, callback) {
    //this._listener[eventName]没有值则将listener定义为[](数组)。
    listener.push(callback);
    this._listener[eventName] = listener;
}

 //触发事件
Emitter.prototype.trigger = function(eventName) {
    var args = Array.prototype.slice.apply(arguments).slice(1);
    //atgs为获得除了eventName后面的参数(注册事件的参数)
    var listener = this._listener[eventName];

    if(!Array.isArray(listener)) return;//自定义事件名不存在
    listener.forEach(function(callback) {
        try {
            callback.apply(this, args);
        }catch(e) {
            console.error(e);
        }
    })
}
//实例
var emitter = new Emitter();
    emitter.bind("myevent", function(arg1, arg2) {
        console.log(arg1, arg2);
    });

    emitter.bind("myevent", function(arg1, arg2) {
        console.log(arg2, arg1);
    });

    emitter.trigger('myevent', "a", "b");


事件广播(dispatchEvent)

一般我们在元素上绑定事件后,是靠用户在这些元素上的鼠标行为来捕获或者触发事件的,或者自带的浏览器行为事件,比如click,mouseover,load等等,有些时候我们需要自定义事件或者在特定的情况下需要触发这些事件。这个时候我们可以使用IE下fireEvent方法,高级浏览器(chrome,firefox等)有dispatchEvent方法。

ie下的例子:

//document上绑定自定义事件ondataavailable
document.attachEvent('ondataavailable', function (event) {
    alert(event.eventType);
});
var obj=document.getElementById("obj");
//obj元素上绑定click事件
obj.attachEvent('onclick', function (event) {
alert(event.eventType);
});
//调用document对象的createEventObject方法得到一个event的对象实例。
var event = document.createEventObject();
event.eventType = 'message';
//触发document上绑定的自定义事件ondataavailable
document.fireEvent('ondataavailable', event);
//触发obj元素上绑定click事件
document.getElementById("test").onclick = function () {
    obj.fireEvent('onclick', event);
};

高级浏览器(chrome,firefox等)的例子:

//document上绑定自定义事件ondataavailable
document.addEventListener('ondataavailable', function (event) {
    alert(event.eventType);
}, false);
var obj = document.getElementById("obj");
//obj元素上绑定click事件
obj.addEventListener('click', function (event) {
    alert(event.eventType);
}, false);
//调用document对象的 createEvent 方法得到一个event的对象实例。
var event = document.createEvent('HTMLEvents');
// initEvent接受3个参数:
// 事件类型,是否冒泡,是否阻止浏览器的默认行为
event.initEvent("ondataavailable", true, true);
event.eventType = 'message';
//触发document上绑定的自定义事件ondataavailable
document.dispatchEvent(event);
var event1 = document.createEvent('HTMLEvents');
event1.initEvent("click", true, true);
event1.eventType = 'message';
//触发obj元素上绑定click事件
document.getElementById("test").onclick = function () {
    obj.dispatchEvent(event1);
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值