JavaScript事件委派 - 行为

时间:2013-11-26 20:17:44

标签: javascript css

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

这是我的HTML

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

我希望整个部分都是可点击的,但在此时点击h1 p中的sectionevent.target元素h1或{{1}而不是p,所以if语句中的表达式失败...

section

我已经有了直接绑定的解决方案,但是在事件委托的相同结果中实现它会很好。 这是jsFiddle

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);
}

提前致谢!

3 个答案:

答案 0 :(得分:3)

处理完点击后,您可以从目标开始走可视树,找到所需的信息 你可以通过类型(节点名称),按标签来寻找......为了这个例子,我只是寻找元素以获得'数据链接'属性,如果我没有在目标上找到一个,但是你有很多选择。

编辑:另一个想法是使用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:我没理解为什么你把事件挂钩在元素的父元素上,可能更简单,不去做。 : - )

答案 1 :(得分:2)

我找到了 CSS pointer-events

的解决方案

jsFiddle with CSS


.myClass * {
    pointer-events: none;
}

JavaScript

jsFiddle with 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"));
            }
        });
    }
}());

答案 2 :(得分:1)

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

Demo

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)。