我的代码大致如下(我删除了一些部分,因为它们无关紧要):
Library.focus = function(event) {
var element, paragraph;
element = event.srcElement;
paragraph = document.createElement("p");
paragraph.innerText = element.innerText;
element.parentNode.insertBefore(paragraph, element); // Line #1
element.parentNode.removeChild(element); // Line #2
};
我遇到的问题是,我编号为第2行的最后一个电话会抛出这个:
Uncaught Error: NOT_FOUND_ERR: DOM Exception 8
请注意,前一行#1工作正常,并在其前插入段落节点。 Element是一个现有元素,element.parentNode和element.parentNode.removeChild也都存在。
我发现这不合逻辑,因为元素根据定义是其parentNode的子元素。 也许StackOverflow能够在这里帮助我吗?
答案 0 :(得分:8)
来自mdn docs:
如果child实际上不是元素节点的子节点,则该方法 抛出一个例外。如果孩子实际上是一个,也会发生这种情况 呼叫时元素的子节点,但被事件删除 在尝试删除元素的过程中调用的处理程序(例如, 模糊。)
我可以在jsfiddle
中重现此错误基本上,你聚焦元素,触发一个删除,触发模糊,移动元素,使元素不再是父元素。
答案 1 :(得分:2)
如果您尝试在onblur处理程序中修改您尝试在另一个处理程序中删除的同一节点(例如onfocus,keydown等),则第一次调用removeChild
将触发onblur处理程序在实际删除节点之前。
如果onblur处理程序然后修改节点以使其父节点发生更改,则控件将从onblur处理程序返回到onfocus处理程序中的removeChild
调用,然后该函数将尝试删除节点并因您描述的异常而失败。 / p>
在你的onfocus处理程序中调用removeChild
之前检查孩子是否存在的任何数量都是徒劳的,因为这些检查将在触发onblur处理程序之前发生。
除了重新安排事件处理和节点修改之外,最好的办法是在try catch块中处理异常。
以下代码将显示onflur事件处理程序如何在onfocus中removeChild
实际删除子项之前运行。它也在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
答案 2 :(得分:0)
不要将事件作为Library.focus函数的参数传递。它会起作用。
Library.focus = function() {
var element, paragraph;
element = event.srcElement;
paragraph = document.createElement("p");
paragraph.innerText = element.innerText;
element.parentNode.insertBefore(paragraph, element); // Line #1
element.parentNode.removeChild(element); // Line #2
};