如果您尝试在 onblur 处理程序中修改您尝试在另一个处理程序中删除的同一节点(例如 onfocus、keydown 等),那么第一次调用removeChild
将在实际删除节点之前触发 onblur 处理程序。如果 onblur 处理程序随后修改节点以使其父节点发生更改,则控制将从 onblur 处理程序返回到removeChild
onfocus 处理程序中的调用,然后该处理程序将尝试删除节点并失败并出现您描述的异常。
在调用 onfocus 处理程序之前检查孩子是否存在的任何数量removeChild
都是徒劳的,因为这些检查将在触发 onblur 处理程序之前发生。
除了重新安排事件处理和节点修改之外,最好的办法可能是在 try catch 块中处理异常。
以下代码将显示 onblur 事件处理程序removeChild
在 onfocus 实际移除子项之前如何运行。它也在jsfiddle
html
<div id="iParent">
<input id="i">
</div>
js
var input = document.querySelector("#i"),
inputParent = document.querySelector('#iParent');
input.onblur = function() {
console.log('onblur : input ' + (input.parentNode ? 'has' : 'doesnt have')
+ ' a parent BEFORE delete');
try {
inputParent.removeChild(input);
} catch (err) {
console.log('onblur : removeChild failed, input '
+ (input.parentNode ? 'has' : 'doesnt have') + ' a parent');
return false;
}
console.log('onblur : child removed');
};
input.onfocus = function() {
console.log('onfocus : input ' + (input.parentNode ? 'has' : 'doesnt have')
+ ' a parent BEFORE delete');
try {
inputParent.removeChild(input);
} catch (err) {
console.log('onfocus : removeChild failed, input '
+ (input.parentNode ? 'has' : 'doesnt have') + ' a parent');
return false;
}
console.log('onfocus : child removed');
};
专注于输入字段后的控制台输出将是
onfocus : input has a parent BEFORE delete
onblur : input has a parent BEFORE delete
onblur : child removed
onfocus : removeChild failed, input doesnt have a parent