Javascript 未能执行';removeChild';在';节点';

Javascript 未能执行';removeChild';在';节点';,javascript,Javascript,我用它在我的网站上突出显示代码,但有时在我的日志中会出现如下Javascript错误: 未捕获NotFoundError:未能在“节点”上执行“removeChild”:要删除的节点不再是此节点的子节点。可能是在“模糊”事件处理程序中移动的 Uncaught NotFoundError:尝试在不存在节点的上下文中引用该节点 以下是attachEvent()函数代码: function attachEvent(obj, type, func, scope) { function handl

我用它在我的网站上突出显示代码,但有时在我的日志中会出现如下Javascript错误:

未捕获NotFoundError:未能在“节点”上执行“removeChild”:要删除的节点不再是此节点的子节点。可能是在“模糊”事件处理程序中移动的

Uncaught NotFoundError:尝试在不存在节点的上下文中引用该节点

以下是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);
    }
};

有人能帮我解决这个问题吗?

我不得不处理同样的问题,答案令人困惑,而且违反直觉。嗯,它有它的逻辑,但会导致非琐碎的行为

本质上,当从DOM树中删除节点时,它会触发
blur
事件(在
focusout
事件之前)

因此,当您调用
removeChild
时,
blur
事件将再次触发,但这次
textarea
仍定义了其
parentNode
,但
textarea
不再属于其父节点的子节点!(是的,读两遍。或者更多。)

虽然Firefox已经有相当长的一段时间了,但现在Chrome浏览器中也出现了这种情况

作为一种解决方法,您可以删除附加的事件侦听器:

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
语句,但是。。。啊

2016年更新 当然,使用jQuery这样的框架将为您节省大量的工作,将事件监听器与
one
连接起来,但此功能也将用于:


而不是
textarea.parentNode.removeChild(textarea)
您可以使用
textarea.parentNode.innerHTML='
或类似的东西,具体取决于您的上下文。

我在这里冒险,假设您中的一些人发现了这个问题,因为您搜索了上面引用的错误:

“节点”上的“removeChild”:要删除的节点不再是子节点 这个节点的。可能是在“模糊”事件处理程序中移动的

我正在使用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;
    }
});

如果没有更好的解决方案,我会非常惊讶,但希望这能帮助一些人,并可能获得一些建设性的意见。

我在一个简单的jQuery脚本上发现了相同的错误消息。 当我试图获取元素$('#element').height()的高度时,我在控制台上看到了相同的错误

元素已存在且为$('#element')。长度为1

带有console.log($('#element')的元素的日志类似于jQuery对象,但有许多重复的方法

经过大量调试后,我发现添加$(document).on('DOMContentLoaded-DOMNodeInserted')事件处理程序会使jQuery对象出现这种奇怪的情况


希望这能帮助别人,因为很难找到它。

我使用时间延迟,它对我来说就是这样

// set up handler for lost focus attachEvent(textarea, 'blur', function(e) { setTimeout(function() { textarea.parentNode.removeChild(textarea); removeClass(highlighterDiv, 'source'); }, 0); }); //为失去焦点设置处理程序 attachEvent(文本区域,'blur',函数(e) { setTimeout(函数(){ textarea.parentNode.removeChild(textarea); removeClass(highlighterDiv,“源”); }, 0); });
我犯了这个错误,但上面的一切都帮不了我,最终我只得到了一个简单的答案:

if (img.parentNode) {
    body.removeChild(img);
}

这对我来说非常合适。

为什么不使用jquery:

$("#element_id").remove();

每次执行该方法时,您都需要检查该元素是否是给定父元素的子元素

if(box.parentElement === parentBox) {
    parentBox.removeChild(box);
}

虽然这个问题的经典答案是这是JS代码中的一个bug,但是React 16有一个主要bug,这意味着任何修改DOM的浏览器/扩展机制都会破坏React

谷歌浏览器内置的翻译功能是最常见的罪魁祸首

GitHub问题:

最小大小写:(只需在Chrome中手动右键单击“Translate to”并从日语中选择,然后单击按钮)

解决方法:


尝试使用Google Chrome翻译您的站点(右键单击站点并选择“翻译为英语”。如果您在控制台中看到错误,则您知道它是由Google translate引起的

相关GitHub问题:


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);
  }
}
在应用程序呈现之前运行此代码。请记住,这会对性能造成轻微影响


Shuhei Kagawa的解决方案

中呈现文本

// 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>

//案例1
{条件&“欢迎”}
某物
//案例1的解决方法
{条件&&Welcome}
某物
//案例2
{条件&&Something}
欢迎
//案例2的解决方法
{条件&&Something}
欢迎
详细说明可在此处找到:

从程序触发的事件类型可能与Dom的默认操作不同。如果您检查类型,并使用If(type=='typeYouWant')作为保护子句,则可能会跳过代码的不必要执行。控制台记录事件以检查是否存在可以隔离的'type'

   formEditEl.addEventListener('blur', this._cancelEdit.bind(this));

  _cancelEdit(e) {
    if (e.type === "change") document.querySelector('.form__edit').remove();
    };

什么是textarea html?如果可能,制作一个fiddle.textarea=document.createElement('textarea')您可以在完整的源代码中使用它。您可以尝试此演示,但错误通常不会出现。我只是在记录javascript错误的网站日志中有时会遇到错误。attachEve
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);
  }
}
// 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>

   formEditEl.addEventListener('blur', this._cancelEdit.bind(this));

  _cancelEdit(e) {
    if (e.type === "change") document.querySelector('.form__edit').remove();
    };