如何在使用 outerHTML 更改内容后获取对新 DOM 对象的引用

How to get reference to the new DOM object after changing content with outerHTML?

本文关键字:获取 DOM 引用 对象 outerHTML      更新时间:2023-09-26

我有一个部门,我需要在事件时更改其外部 HTML。问题是在设置outerHTML时,除非我再次显式捕获它,否则我无法引用新选择的 DOM 对象。

有没有办法在调用outerHTML时直接更新变量引用(在我的例子中是下面div变量的引用)?

$("#changeDiv").click(function(){
  var div = $(this).prev();
  div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
  console.log(div); // logs [div#imFirstDiv, prevObject: n.fn.init[1], context: button#changeDiv]
  
  // the following line does not affect the newly added division 
  // since the var `div` references the old DOM object
  // unless I add div = $(this).prev(); before setting the html of 
  // the paragraph it will not set it
  div.find('p').html('Override'); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

我已经通过获取要替换的标签的引用元素(兄弟或父元素)来解决这个问题。

这是一个不依赖于您要更改哪个元素的函数:

function replaceElement(ele, outerHTML)
{
  var parent = false, refEle;
  //if element that's going to be changed has previousElementSibling, take it as reference. If not, the parentElement will be the reference.
  if (ele.previousElementSibling !== null)
    refEle = ele.previousElementSibling;
  else
  {
    refEle = ele.parentElement;
    //indicate that parentElement has been taken as reference
    parent = true;
  }
  //change the outerHTML
  ele.outerHTML = outerHTML;
  //return the correct reference
  if (parent)
    return refEle.firstElementChild;
  else return refEle.nextElementSibling;
}

因此,在您的情况下,您将以这种方式调用它:

div[0] = replaceElement(div[0], '<div id="imSecondtDiv"> <p> World </p> </div>');

我希望它也能与jQuery一起使用,因为我只用原生javascript编写所有脚本。

正如您所看到的,更改outerHTML会使事情变得有点奇怪,因为您正在完全替换原始元素但仍引用旧元素。

最好创建一个 新div ,将其添加到旧after(),然后remove()旧。这样可以将div的位置保持在正确的位置。

$("#changeDiv").click(function(){
  // get the oldDiv
  var oldDiv = $(this).prev();
  // Create a newDiv
  var newDiv = $('<div id="imSecondtDiv"> <p> World </p> </div>');
  // add newDiv after oldDiv one, then remove oldDiv from the DOM.
  oldDiv.after(newDiv).remove();
  
  // now you still have the reference to newDiv, so do what you want with it
  newDiv.find('p').html('Override'); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

使用外部HTML

如果你真的需要使用outerHTML,你可以简单地再次抓取$(this).prev()

$("#changeDiv").click(function(){
  var div = $(this).prev();
  div[0].outerHTML = `<div id="imSecondtDiv"> <p> World </p> </div>`;
  // the "new" div is now before the button, so grab the reference of THAt one
  div = $(this).prev();
  // the following line does not affect the newly added division 
  // since the var `div` references the old DOM object
  // unless I add div = $(this).prev(); before setting the html of 
  // the paragraph it will not set it
  div.find('p').html('Override'); 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imFirstDiv"> <p> Hello </p> </div>
<button id="changeDiv" >Change Div 1</button>

有没有办法在调用outerHTML时直接更新变量引用?

不。根据MDN Web Docs:

当元素将在文档中被替换时,设置了 outerHTML 属性的变量仍将保留对原始元素的引用。

const p = document.querySelector('p');
p.outerHTML = '<p>Goodbye, world!</p>';
console.log(p.textContent);
<p>Hello, world!</p>

但是,作为一种解决方法,您可以创建一个实时HTMLCollection,以便在更新之前和之后从中获取元素:

const Ps = document.getElementsByTagName('p');
Ps[0].outerHTML = '<p>Goodbye, world!</p>';
console.log(Ps[0].textContent);
<p>Hello, world!</p>