当覆盖锚标记时,更改innerHTML会破坏parentNode吗?怎么修?

时间:2016-01-11 18:05:17

标签: javascript dom

我为click事件设置了两个事件处理程序。一个在表中的所有<th>,另一个在文档上。

<th>处理程序中的部分代码更改了单击元素的innerHTML。至关重要的是,我认为th代码中有一个锚标记。

文档处理程序中的部分代码检查单击元素的parentNode。

出现这两个事实导致了问题。如果我注释掉innerHTML修改行,一切正常。如果我把它留在里面,我对元素的parentNode得到“null”。

这是一个已知问题,如果是这样,解决方案是什么?这是Chrome中的错误,还是JavaScript / DOM因某种原因而出现的行为?

function isInside(eChild, eParent) {
  alert('element is ' + eChild);
  if (eChild === eParent) {
    return true;
  }

  if (eChild === document) {
    return false;
  }

  return isInside(eChild.parentNode, eParent);
}

function init1() {
  document.getElementById('th').addEventListener('click', function(e) {
    document.getElementById('th').innerHTML = '<a href="#">Changed</a>';
  });
}

function init2() {
  document.addEventListener('click', function(e) {
    if (isInside(e.target, document.getElementById('table'))) {
      alert('found in table');
    } else {
      alert('not found in table');
    }
  });
}

init1();
init2();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<table id="table">
  <thead>
    <tr>
      <th id="th"><a href="#">Click me</a>
      </th>
    </tr>
  </thead>
</table>

如果您注释掉

document.getElementById('th').innerHTML = '<a href="#">Changed</a>';
在JavaScript中

行,您将体验到所需的行为。

我认为这是因为事件是在<a>而不是<th>上触发的,然后我在innerHTML调用中用新的替换该锚点。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:3)

发生这种情况是因为单击的元素在请求其parentNode时不再存在于文档中。你用一个完全不同的元素取而代之。

而不是更改父元素的innerHTML,因此替换用新元素单击的元素,只需更改现有元素。

我已经缩小了下面的完整演示以节省空间,但解决方案的核心在于:

var th = document.getElementById('th');
var link = th.querySelector('a');

th.addEventListener('click', function(e) {
  link.textContent = 'Changed';
});

这是演示:

&#13;
&#13;
function isInside(eChild, eParent) {
  alert('element is ' + eChild);
  if (eChild === eParent)  return true;
  if (eChild === document) return false;
  return isInside(eChild.parentNode, eParent);
}

var th = document.getElementById('th');
var link = th.querySelector('a');

th.addEventListener('click', function(e) {
  link.textContent = 'Changed';
});

document.addEventListener('click', function(e) {
  if (isInside(e.target, document.getElementById('table'))) alert('found in table');
  else alert('not found in table');
});
&#13;
<table id="table"><thead><tr><th id="th"><a href="#">Click me</a></th></tr></thead></table>
&#13;
&#13;
&#13;