我正在使用http://alexgorbatchev.com/SyntaxHighlighter/突出显示我网站上的代码,但有时候在我的日志中我会收到像这样的Javascript错误:
未捕获NotFoundError:无法在“节点”上执行“removeChild”:要删除的节点不再是此节点的子节点。也许它被移动到'模糊'事件处理程序中?
Uncaught NotFoundError:尝试在不存在的上下文中引用Node。
// set up handler for lost focus
attachEvent(textarea, 'blur', function(e)
{
textarea.parentNode.removeChild(textarea);
removeClass(highlighterDiv, 'source');
});
这是attachEvent()函数代码:
function attachEvent(obj, type, func, scope)
{
function handler(e)
{
e = e || window.event;
if (!e.target)
{
e.target = e.srcElement;
e.preventDefault = function()
{
this.returnValue = false;
};
}
func.call(scope || window, e);
};
if (obj.attachEvent)
{
obj.attachEvent('on' + type, handler);
}
else
{
obj.addEventListener(type, handler, false);
}
};
任何人都可以帮忙解决此问题吗?
答案 0 :(得分:48)
我不得不处理同样的问题,答案是混乱和反直觉。嗯,它有其逻辑,但会导致非平凡的行为。
基本上,当从DOM树中删除节点时,它会触发blur
事件(以及focusout
事件之前)。
因此,当您致电removeChild
时,blur
事件再次被重新启动,但这次textarea
仍然已定义parentNode
,但textarea
不再是其父母的子女之一! (是的,请阅读两次。或者更多。)
目前在Chrome中发生这种情况,虽然Firefox已经有planned to do the same一段时间了。
作为解决方法,您可以删除附加的事件侦听器:
var onblur = function(e) {
detachEvent(textarea, 'blur', onblur);
textarea.parentNode.removeChild(textarea);
removeClass(highlighterDiv, 'source');
};
attachEvent(textarea, 'blur', onblur);
我假设您有一些detachEvent
函数来删除事件侦听器。根据您的需要调整代码。
或者,您可以在侦听器函数中的textarea上设置标志(如属性,属性或更好的范围变量),并在继续删除节点之前检查它:
var removed = false;
attachEvent(textarea, 'blur', function(e) {
if (removed) return;
removed = true;
textarea.parentNode.removeChild(textarea);
removeClass(highlighterDiv, 'source');
});
您还可以在删除之前检查textarea
是否实际上是parentNode
的子节点,但这样的测试是非常违反直觉的(至少对我而言)我不建议这样做因为担心将来会改变这种行为。
最后,你总是可以依赖try...catch
声明,但是......呃。
自然地,使用像jQuery这样的框架可以为你节省大量使用one
附加事件监听器的工作,但是这个功能也将来到standard addEventListener
:
textarea.addEventListener('blur', handler, { once: true });
答案 1 :(得分:5)
我在这里走出困境并假设有些发现此问题的人在这里,因为你搜索了上面引用的错误:
' removeChild之' on'节点':要删除的节点不再是孩子 这个节点。也许它被移动了一个模糊的'事件处理程序?
我正在使用jQuery& DataTables 1.10.6并且这个错误确实出现在我正在更新单元格值的blur()
事件中。我的解决方案是在事件中添加一个条件,如下所示:
var blur = false;
$('table').on('blur', 'td select', function() {
if (!blur) {
blur = true;
var cell = $(this).closest('td');
table.cell(cell).data('example data');
blur = false;
}
});
如果没有更好的解决方案,我会感到非常惊讶,但希望这可以帮助某人,也许可以获得一些建设性的评论。
答案 2 :(得分:5)
虽然这个问题的经典答案是它是JS代码中的一个错误,但是React 16存在一个主要错误,这意味着任何修改DOM的浏览器/扩展机制都会破坏React。
Google Chrome内置的翻译功能是最常见的罪魁祸首。
GitHub问题:https://github.com/facebook/react/issues/11538
最小案例:https://p93xxmr0rq.codesandbox.io/(只需在Chrome中右键单击“翻译为”,然后从日语中选择,然后点击按钮)
解决方法:How to disable google translate from html in chrome
<meta name="google" content="notranslate">
答案 3 :(得分:2)
而不是textarea.parentNode.removeChild(textarea);
您可以使用textarea.parentNode.innerHTML = ''
或类似内容,具体取决于您的具体情况。
答案 4 :(得分:2)
我使用时间延迟,它对我有用。
// set up handler for lost focus attachEvent(textarea, 'blur', function(e) { setTimeout(function() { textarea.parentNode.removeChild(textarea); removeClass(highlighterDiv, 'source'); }, 0); });
答案 5 :(得分:1)
我在一个简单的jQuery脚本上发现了相同的错误消息。 当我试图获得元素$('#element')。height()的高度时,我在控制台上看到了同样的错误。
元素存在且$('#element')。长度为1。
使用console.log($('#element'))的元素日志就像一个jQuery对象,但重复了很多方法。
经过大量的调试后,我发现添加一个$(document).on('DOMContentLoaded DOMNodeInserted')事件处理程序给jQuery对象带来了这个奇怪的东西。
希望这有助于某人造成这很难找到。
答案 6 :(得分:1)
我收到了这个错误,上面的任何内容都没有帮助我,最终我的结果很简单:
[onclick*='set']
对我来说非常适合。
答案 7 :(得分:0)
尝试使用Google Chrome浏览器翻译您的网站(右键单击该网站,然后选择“翻译成英语”。如果您在控制台中看到错误,则表明它是由Google翻译引起的。
相关的GitHub问题:https://github.com/facebook/react/issues/11538。
Dan Abramov的解决方法:
if (typeof Node === 'function' && Node.prototype) {
const originalRemoveChild = Node.prototype.removeChild;
Node.prototype.removeChild = function(child) {
if (child.parentNode !== this) {
if (console) {
console.error('Cannot remove a child from a different parent', child, this);
}
return child;
}
return originalRemoveChild.apply(this, arguments);
}
const originalInsertBefore = Node.prototype.insertBefore;
Node.prototype.insertBefore = function(newNode, referenceNode) {
if (referenceNode && referenceNode.parentNode !== this) {
if (console) {
console.error('Cannot insert before a reference node from a different parent', referenceNode, this);
}
return newNode;
}
return originalInsertBefore.apply(this, arguments);
}
}
在呈现您的应用之前运行此代码。请记住,这会对性能造成轻微影响。
香川修平的解决方法
渲染<span>
中的文本。
// Case 1
<div>
{condition && 'Welcome'}
<span>Something</span>
</div>
// A workaround for case 1
<div>
{condition && <span>Welcome</span>}
<span>Something</span>
</div>
// Case 2
<div>
{condition && <span>Something</span>}
Welcome
</div>
// A workaround for case 2
<div>
{condition && <span>Something</span>}
<span>Welcome</span>
</div>
可在此处找到详细说明: https://github.com/facebook/react/issues/11538#issuecomment-390386520
答案 8 :(得分:0)
从程序中触发的事件类型可能与 Dom 的默认操作不同。如果您检查类型并使用 if (type === 'typeYouWant') 作为保护子句,则可能会跳过不需要的代码执行。控制台记录事件以检查是否存在可以隔离的“类型”。
formEditEl.addEventListener('blur', this._cancelEdit.bind(this));
_cancelEdit(e) {
if (e.type === "change") document.querySelector('.form__edit').remove();
};
答案 9 :(得分:-1)
每次执行方法时都需要检查元素是否是给定父元素的子元素。
if(box.parentElement === parentBox) {
parentBox.removeChild(box);
}
答案 10 :(得分:-2)
为什么不使用jquery:
$("#element_id").remove();