理解事件委托处理

Understanding Event Delegation Handling

本文关键字:处理 事件      更新时间:2023-09-26

我试图在同一页面上为不同的表单使用事件委托。然而,当我试图提交表单时,我遇到了一个有趣的问题。

我尝试在一个表单上使用'click'(用于提交按钮),因为我知道事件委托本身就会在整个表单上设置'click'。

然而,问题来自于'click'事件实际上是在整个页面上设置的,而不仅仅是表单或按钮元素。因此,无论在哪里单击页面,都会触发表单的"click"事件。所有浏览器都是这样。

同样的事情也发生在'change'事件中。当我在表单上设置'change'事件时,它会为表单的子字段和特定表单节点之外的其他字段触发。

所以,虽然我知道以前有人问过关于事件委托的问题,但他们并没有真正回答这个问题。这是个问题吗?也许这就是事件委托的工作方式?但是,如果是这样,那么为整个文档触发事件不是浪费内存吗?解决方案是什么?

另外,是否有一种跨浏览器的方式来阻止纯Javascript的传播?我找到的最好的是在Quirksmode.org上:

function doSomething(e)
{    
    if (!e) var e = window.event;
    e.cancelBubble = true;
    if (e.stopPropagation) e.stopPropagation();
}

我知道我可以在触发时按类型过滤事件,但这是唯一可以做的事情吗?请帮助我理解这一点!

编辑:

具体的问题是是否将事件委托给表单以处理其特定字段上的事件也将/可以触发文档其余部分的事件?如果有,该如何处理?如果这不是事件委托的预期行为,那么可能是什么原因导致的呢?

一个事件将通过它的祖先冒泡。如果你有HTML结构;

<div>
    <h2>
        <span>
            <input />
        </span>
        <strong>
            Blah
        </strong>

…当你点击输入元素时,你会看到点击事件起源于input元素,然后弹出它的祖先(span, h2, div, body, document)。它不会在strong上触发,因为它不是祖先。请参阅http://jsfiddle.net/2QQFS/获取示例(当您单击其中一个<input />框时查看控制台)。

您的<form />不应该嵌套。如果您在每个<form />元素上附加事件处理程序,并在其他表单的其他表单的触发事件上看到事件,我会验证您的HTML (http://validator.w3.org),以确保您没有错过某个地方的结束标记,或其他东西。

要查看事件源自哪个元素,可以使用e.targete.srcElement (IE <8)。

您没有显示注册事件侦听器的实际代码。

有这个小提琴与preventDefault和stopPropagation。

我希望这是不言自明的。如果你喜欢,用叉子把小提琴叉开。

注意form2。input没有事件监听器,事件会冒泡到outerDiv。

form1是根据相关的用户控制执行停止和预防的。

输出区域应该说明发生了什么。

<div id="outerDiv">
<div>
    <input id="pd" value="1" type="checkbox">Prevent Default in form1 keydown</input>
</div>
<div>
    <input id="sp" value="1" type="checkbox">Stop Propagation in form1 keydown</input>
</div>
<div>
    <button id="clear">Clear Output</button>
</div>
<form id="form1" action="">
    <div>
        <label>input of form1
            <input type="text" />
        </label>
    </div>
</form>
<form id="form2" action="">
    <div>
        <label>input of form2
            <input type="text" />
        </label>
    </div>
</form> <pre id="output">
    watch this spot
</pre>
</div>

JS

window.addEventListener('DOMContentLoaded', function (event) {
// console.log("DOMContentLoaded event handler ...");
var form1 = document.getElementById('form1');
var form2 = document.getElementById('form2');
var output = document.getElementById('output');
var div = document.getElementById('outerDiv');
var clear = document.getElementById('clear');
clear.addEventListener('click', function (event) {
    output.textContent = (''n' + clear.id + '''s ' + event.type + ' event handler for ' + event.srcElement.localName + ' clears output');
}, false);
console.dir(output);
div.addEventListener('keydown', function (event) {
    output.textContent += (''n' + div.id + '''s ' + event.type + ' event handler for ' + event.srcElement.localName + ' notices  ''' + event.srcElement.value + '''');
}, false);
form1.addEventListener('keydown', function (event) {
    output.textContent += (''n' + form1.id + '''s ' + event.type + ' event handler for ' + event.srcElement.localName + ' notices  ''' + event.srcElement.value + '''');
    // prevents default of generating an input event
    if (document.getElementById('pd').checked) {
        event.preventDefault();
        output.textContent += (''n't' + form1.localName + '''s ' + event.type + ' event handler does preventDefault');
    }
    // stops propagation up to div
    if (document.getElementById('sp').checked) {
        event.stopPropagation();
        output.textContent += (''n't't' + form1.localName + '''s ' + event.type + ' event handler does stopPropagation');
    }
}, false);
form1.addEventListener('input', function (event) {
    output.textContent += (''n' + form1.id + '''s ' + event.type + ' event handler for ' + event.srcElement.localName + ' notices  ''' + event.srcElement.value + '''');
}, false);
}, false);