从零开始学_JavaScript_系列(31)——事件代理/事件委托

(49)事件代理/事件委托

github:

https://github.com/qq20004604/some_demo/tree/master/%E4%BA%8B%E4%BB%B6%E4%BB%A3%E7%90%86


①简单来说,利用事件的捕获-触发-冒泡三阶段的机制,在冒泡阶段,父级(或更高级)结点处理触发事件,而非子节点(事件触发结点)触发事件。

 

从而避免给每个子节点绑定事件所带来的大量事件问题,(委托往往只需要一个即可)

 

完全不懂的可以参照链接:

http://www.cnblogs.com/owenChen/archive/2013/02/18/2915521.html

 

②如代码:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件代理</title>
</head>
<body>
<ul id="test">
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>
        eeee
        <span>ffff</span>
        gg
    </li>
</ul>

<script>
    function setEvent() {
        document.querySelector("#test").addEventListener("click", function (evt) {
            console.log(evt);   //这个获取点击事件
            console.log(evt.target);    //这个是获取触发点击事件的dom,是最底层的DOM(即事件目标)
            console.log(evt.target.nodeName);   //显示HTML标签名
            if (evt && evt.target.nodeName === 'LI') {
                alert("文本内容为:" + evt.target.innerHTML + "的li结点被触发了");
            }
        })
    }
    setEvent();
</script>
</body>
</html>

③优点:

【1】当dom结构单一时,可以省去大量的绑定事件的问题;

【2】当动态添加、删除子节点时(如上面的li),可以省去绑定、移除子节点的功夫,减少业务复杂度;

 

④缺点:

【1】DOM结构复杂时,很难满足需求,如上面最后一个li标签,点击span标签范围是不能触发事件的;(我觉得有办法处理,即跟踪其冒泡阶段,但是暂时不知道怎么写)

【2】如果父级DOM下,某些DOM有响应事件,某些DOM没有响应事件,那么需要进行额外的逻辑判断进行处理。

 

⑤在IE情形下,特别是兼容低版本IE时,不能简单的这么写。

参考链接:

http://www.w3cmark.com/2016/439.html

 

代码如下:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8">
    <title>事件代理</title>
</head>
<body>
<ul id="test">
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>
        eeee
        <span>ffff</span>
        gg
    </li>
</ul>

<script>
    //参数依次为:委托元素,选择器(支持类、id和元素),事件类型,回调函数
    function delegateEvent(parentElement, selector, eventType, fn) {
        if (parentElement.addEventListener) {
            //普通的,然后触发回调函数
            parentElement.addEventListener(eventType, eventfn);
        } else {
            //兼容的处理,然后触发回调函数
            parentElement.attachEvent("on" + eventType, eventfn);
        }

        function eventfn(e) {
            //事件或者是兼容性处理的window的事件
            console.log(e);
            var e = e || window.event;
            var target = e.target || e.srcElement;
            if (matchSelector(target, selector)) {
                if (fn) {
                    //用call将目标dom作为this指向的对象
                    fn.call(target, e);
                }
            }
        }
    }
    /**
     *  选择器匹配
     *  不支持组合,只支持id、类、html标签名
     */
    function matchSelector(element, selector) {
        // 匹配id
        if (selector.charAt(0) === "#") {
            return element.id === selector.slice(1);
        }
        // 匹配类名
        if (selector.charAt(0) === ".") {
            return (" " + element.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
        }
        // 匹配HTML标签名
        return element.tagName.toLowerCase() === selector.toLowerCase();
    }

    //获取父节点
    var parentNode = document.getElementById("test");
    //调用事件委托函数,父节点作为代理结点,第二个参数是选择器,支持类名、标签名和id(但不能组合),第三个是事件,第四个参数是回调函数
    delegateEvent(parentNode, "li", "click", function (e) {
        console.log(e);
        console.log(this);
        alert("1");
    })
</script>
</body>
</html>


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值