如果删除DOM元素,那么以该元素开始的任何事件是否继续浮动? [英] If you delete a DOM element, do any events that started with that element continue to bubble?

查看:93
本文介绍了如果删除DOM元素,那么以该元素开始的任何事件是否继续浮动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我删除了用于启动事件泡泡的DOM元素,或者其孩子启动了事件气泡,我应该期待什么行为?如果元素被删除,它将继续浮动吗?

What behavior should I expect if I delete a DOM element that was used to start an event bubble, or whose child started the event bubble - will it continue to bubble if the element is removed?

例如 - 让我们说你有一张表,想要检测表单元格上的点击事件。另一件JS已经执行了一个AJAX请求,一旦请求完成,最终将完全替换表。

For example - lets say you have a table, and want to detect click events on the table cells. Another piece of JS has executed an AJAX request that will eventually replace the table, in full, once the request is complete.

如果我点击表格立即,会发生什么在成功完成AJAX请求后,表被替换了?我问,因为我看到一些行为,点击事件似乎没有冒泡 - 但很难重复。

What happens if I click the table, and immediately after the table gets replaced by a successful completion of an AJAX request? I ask because I am seeing some behavior where the click events don't seem to be bubbling - but it is hard to duplicate.

我正在观看表的父元素上的事件(而不是将事件附加到每个TD),而且它似乎有时不能达到。

I am watching the event on a parent element of the table (instead of attaching the event to every TD), and it just doesn't seem to reach it sometimes.

编辑:再次遇到这个问题,最后到了根目录。根本不是一个事件冒泡的问题!

EDIT: Encountered this problem again, and finally got to the root of it. Was not a event-bubbling issue at all! See my answer below for details.

推荐答案

经验性:这取决于您使用的是什么浏览器; IE取消事件,其他一切(据我所知),继续。

Empirically: It depends on what browser you're using; IE cancels the event, everything else (as far as I can tell) continues it. See the test pages and discussion below.

理论上: Andy E的头有帮助 found that DOM2表示事件应该继续,因为冒泡应该基于树的初始化状态。所以多数人的行为是正确的,IE本身就在这里。 Quelle惊喜。

Theoretically: Andy E's head helpfully found that DOM2 says the event should continue because bubbling should be based on the initial state of the tree. So the behavior of the majority is correct, IE's on its own here. Quelle surprise.

但是:是否与您所看到的是关系的另一个问题。您正在观看表的父元素上的点击次数,当您点击该表时,您所怀疑的是非常少的Ajax完成的竞争条件,可以替换该表,并且点击将丢失。 Javascript解释器中不能存在竞争条件,因为现在,浏览器上的Javascript是单线程的。 (工作线程来了,虽然&— whoo hoo!)但是理论上,点击可能会发生,并在浏览器中被非JavaScript UI线程排队,然后ajax可以完成并替换元素,然后排队UI事件被处理,完全不会发生,或者不起泡,因为该元素不再具有已被删除的父元素。这是否可以实际发生将取决于浏览器实现的批次。如果您在任何开源浏览器上看到它们,您可以查看他们的来源排队UI事件以进行解释。但是实际上除了下面的事件处理程序中的之外的代码的元素是一个不同的事情。

But: Whether that relates to what you're seeing is another question indeed. You're watching for clicks on a parent element of the table, and what you suspect is that very rarely, when you click the table, there's a race condition with an Ajax completion that replaces the table and the click gets lost. That race condition can't exist within the Javascript interpreter because for now, Javascript on browsers is single-threaded. (Worker threads are coming, though — whoo hoo!) But in theory, the click could happen and get queued by a non-Javascript UI thread in the browser, then the ajax could complete and replace the element, and then the queued UI event gets processed and doesn't happen at all or doesn't bubble because the element no longer has a parent, having been removed. Whether that can actually happen will depend a lot on the browser implementation. If you're seeing it on any open source browsers, you might look at their source for queuing up UI events for processing by the interpreter. But that's a different matter than actually removing the element with code within the event handler as I have below.

测试的Chrome 4和Safari 4(例如,WebKit),Opera 10.51,Firefox 3.6,IE6,IE7和IE8的测试版本是

。 IE是唯一一个在您删除元素时取消了事件(并且跨版本一致),其他人都没有。无论是使用DOM0处理程序还是更现代的,似乎都不重要。

Tested Chrome 4 and Safari 4 (e.g., WebKit), Opera 10.51, Firefox 3.6, IE6, IE7, and IE8. IE was the only one that cancelled the event when you removed the element (and did so consistently across versions), none of the others did. Doesn't seem to matter whether you're using DOM0 handlers or more modern ones.

更新:
测试时,IE9和IE10继续的事件,所以IE不符合规范停止在IE8。

UPDATE: On testing, IE9 and IE10 continue the event, so IE noncompliance with spec stops at IE8.

使用DOM0处理程序测试页:

Test page using DOM0 handlers:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
</style>
<script type='text/javascript'>
window.onload = pageInit;

function pageInit() {
    var parent, child;

    parent = document.getElementById('parent');
    parent.onclick = parentClickDOM0;
    child = document.getElementById('child');
    child.onclick = childClickDOM0;
}

function parentClickDOM0(event) {
    var element;
    event = event || window.event;
    element = event.srcElement || event.target;
    log("Parent click DOM0, target id = " + element.id);
}

function childClickDOM0(event) {
    log("Child click DOM0, removing");
    this.parentNode.removeChild(this);
}

function go() {
}

var write = log;
function log(msg) {
    var log = document.getElementById('log');
    var p = document.createElement('p');
    p.innerHTML = msg;
    log.appendChild(p);
}

</script>
</head>
<body><div>
<div id='parent'><div id='child'>click here</div></div>
<hr>
<div id='log'></div>
</div></body>
</html>

使用 attachEvent / addEventListener 处理程序(通过Prototype):

Test page using attachEvent/addEventListener handlers (via Prototype):

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
    font-family: sans-serif;
}
#log p {
    margin:     0;
    padding:    0;
}
</style>
<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js'></script>
<script type='text/javascript'>
document.observe('dom:loaded', pageInit);
function pageInit() {
    var parent, child;

    parent = $('parent');
    parent.observe('click', parentClick);
    child = $('child');
    child.observe('click', childClick);
}

function parentClick(event) {
    log("Parent click, target id = " + event.findElement().id);
}

function childClick(event) {
    log("Child click, removing");
    this.remove();
}

function go() {
}

var write = log;
function log(msg) {
    $('log').appendChild(new Element('p').update(msg));
}
</script>
</head>
<body><div>
<div id='parent'><div id='child'>click here</div></div>
<hr>
<div id='log'></div>
</div></body>
</html>

这篇关于如果删除DOM元素,那么以该元素开始的任何事件是否继续浮动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆