JavaScript事件委派-行为

JavaScript Event Delegation - Behavior

本文关键字:-行 委派 事件 JavaScript      更新时间:2023-10-18

我正在尝试创建网页,为了提高性能,我决定使用事件委派,而不是直接绑定,但我遇到了事件委派的奇怪行为,或者我错过了一些东西。。。

这是我的HTML 的结构

<div>
    <section class="myClass" data-link="section 1">
        <h1>Heading 1</h1>
        <p>Some text....</p>
    </section>
</div>

我想整个部分都是可点击的,但当点击section中的h1p元素时,此时的event.targeth1p,而不是section,所以if语句中的表达式失败了。。。

function delegate(ele) {
    ele.parentNode.addEventListener("click", function (e) {
        if (e.target.nodeName.toLowerCase() === "section" && e.target.classList.contains("myClass")) {
            console.log("delegate " + e.target.getAttribute("data-link"));
        }
    }, false);
}

我已经有了具有直接约束力的解决方案,但如果能在事件授权的情况下取得同样的结果,那就太好了。这是jsFiddle

function direct(ele) {
    [].forEach.call(ele, function (value, index, array) {
        value.addEventListener("click", function(e) {
            console.log("direct " + value.getAttribute("data-link"));
        }, false);
    });
}

提前感谢!

一旦处理了单击,就可以从目标开始遍历可视化树,以找到所需的信息
您可以通过类型(节点名称)、标记等进行查找。。。为了这个例子,如果在目标上找不到datalink属性,我只需要在元素上查找,就可以得到它,但这里有很多选择。

编辑:另一个想法是使用event.currentTarget,以获取您钩住事件的元素。

更新后的小提琴将打印:

delegate call on h1 or p of section 1 

当你点击h1或p1 时

它将打印:

delegate section 1 

当你点击整个部分时。

http://jsfiddle.net/KMJnA/4/

function delegate(ele) {
    ele.parentNode.addEventListener("click", delegateHandler, false);
}
function delegateHandler (e) {
    var target = e.target;  
    var attribute = target.getAttribute("data-link");
    // if target has no attribute
    // seek it on its parent
    if (!attribute) {
         attribute = target.parentNode.getAttribute("data-link");
    }
    if ( target.classList.contains("myClass") ) { 
         console.log("delegate " + attribute);
        } 
    else console.log('delegate call on h1 or p of ' + attribute);
}    

Rq:我不明白为什么要把事件挂在元素的父级上,不挂可能更简单。:-)

我用CSS指针事件找到了解决方案

jsFiddle与CSS


.myClass * {
    pointer-events: none;
}

或者使用JavaScript

jsFiddle与JavaScript


(function () {
    "use strict";
    var ele = document.querySelector(".myClass").parentNode;
    delegate(ele);
    function delegate(ele) {
        ele.addEventListener("click", function (e) {
            var target = e.target;
            while (!(target.nodeName.toLowerCase() === "section" && target.classList.contains("myClass"))) {
                target = target.parentNode;
                if (target === ele) {
                    break;
                }
            }
            if (target.nodeName.toLowerCase() === "section" && target.classList.contains("myClass")) {
                console.log("delegate " + target.getAttribute("data-link"));
            }
        });
    }
}());

将事件侦听器添加到ele而不是ele.parentNode,并使用this而不是e.target

演示

function delegate(ele) {
    ele.addEventListener("click", function (e) {
        if (this.nodeName.toLowerCase() === "section" && this.classList.contains("myClass")) {
            console.log("delegate " + this.getAttribute("data-link"));
        }
    }, false);
}

请注意,e.target是事件调度的元素。但在您不想要的情况下,您想要具有事件处理程序的元素,因此使用this(或ele)。