Javascript:了解事件委派处理

时间:2013-05-26 21:04:39

标签: javascript events javascript-events event-handling event-delegation

我正在尝试在同一页面上使用不同表单的事件委派。但是,在尝试提交表单时,我遇到了一个有趣的问题。

我在一个表单(用于提交按钮)上尝试“点击”,完全了解事件委托固有地在整个表单上设置“点击”。

然而,问题来自于“click”事件实际上是在整个页面上设置的,而不仅仅是表单或按钮元素。因此,无论我在何处单击该页面,都会触发表单的“单击”事件。所有浏览器都会发生这种情况。

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

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

此外,是否有一种跨浏览器的方式来停止纯Javascript中的传播?我找到的最好的是Quirksmode.org

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

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

修改:

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

2 个答案:

答案 0 :(得分:1)

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

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

...然后点击了输入元素,您会在input元素上看到点击事件,然后冒泡其祖先(spanh2,{{1 },divbody)。 不会触发document,因为它不是祖先。有关示例,请参阅http://jsfiddle.net/2QQFS/(单击其中一个strong框时查看控制台。

您的<input />不应该嵌套。如果您在每个<form />元素上附加事件处理程序,并在其他表单的其他表单上查看其他表单上的事件,我将验证您的HTML( http://validator.w3.org)确保你没有错过任何地方的结束标记,或者什么。

要查看事件发起的来自哪个元素,您可以使用<form />e.target(IE <8)。

答案 1 :(得分:0)

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

this fiddle使用preventDefault和stopPropagation。

我希望它不言自明。如果你愿意的话,把小提琴分开。

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

form1是根据相关用户控件执行停止和阻止的那个。

输出区域应该澄清发生了什么。

<强> HTML

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