0

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

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

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

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

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

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

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

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

编辑:

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

4

2 回答 2

1

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

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

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

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

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

于 2013-05-26T21:22:02.480 回答
0

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

让这个小提琴与 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);
于 2013-05-26T23:35:14.983 回答