如何使用Javascript在原地替换DOM元素?

220

我想要替换DOM中的一个元素。
例如,有一个<a>元素,我想要用<span>替换它。

我该如何操作呢?


17
target.replaceWith(element); 是现代(ES5+)实现此操作的方式。 - Gibolt
2
@Gibolt DOM规范与ES有什么关系?此外,它还不是DOM标准的一部分,而ES5已经发布了9年。 - pishpish
1
ES5+ 意味着 ES5 或更高版本。即使 ES5 已经有9年历史了,但是后续版本并不算太老。 - JustinCB
如果你仍然使用StackOverflow,那么选择下面的新标准答案是值得的。 - mikemaccana
10个回答

228

通过使用replaceChild()方法:

<html>
<head>
</head>
<body>
  <div>
    <a id="myAnchor" href="http://www.stackoverflow.com">StackOverflow</a>
  </div>
<script type="text/JavaScript">
  var myAnchor = document.getElementById("myAnchor");
  var mySpan = document.createElement("span");
  mySpan.innerHTML = "replaced anchor!";
  myAnchor.parentNode.replaceChild(mySpan, myAnchor);
</script>
</body>
</html>

7
这个例子无法运行。你需要将脚本块放在 body 的末尾以使其正常工作。此外,只是为了好玩:在操作之后添加一行 [alert(myAnchor.innerHTML)]。 - KooiInc
锚点innerText中的StackOverflow单词拼写错误。 - rahul
8
如果它是根HTML元素,该怎么办? - lisak
谢谢@Bjorn Tipling。我已经创建了一个后续问题,关于如何添加一个id和一个函数到替换的元素,链接在这里:http://stackoverflow.com/questions/15670261/how-to-replace-dom-element-with-js-and-include-an-id-and-a-js-function - JDelage

149

A.replaceWith(span) - 无需父元素

通用形式:

target.replaceWith(element)

比之前的方法好多了/更加干净。

针对您的使用情况:

A.replaceWith(span)

高级用法

  1. 您可以传递多个值(或使用扩展运算符...)。
  2. 任何字符串值都将作为文本元素添加。

示例:

// Initially [child1, target, child3]

target.replaceWith(span, "foo")     // [child1, span, "foo", child3]

const list = ["bar", span]
target.replaceWith(...list, "fizz")  // [child1, "bar", span, "fizz", child3]

安全处理null目标

如果你的目标有可能为空,你可以考虑使用新的?. 可选链运算符。如果目标不存在,什么都不会发生。在此处阅读更多信息

target?.replaceWith?.(element)

相关的DOM方法

  1. 点击查看更多 - child.beforechild.after
  2. 点击查看更多 - parent.prependparent.append

Mozilla文档

支持的浏览器 - 97% Nov '22


13
不支持IE11或Edge 14(现在是2016-11-16)。 - jor
4
请使用Google的Closure或其他转译器将代码转换为ES5。如果有更好、更易于维护的选项,就不应该基于浏览器支持来编写旧代码。 - Gibolt
5
如果我需要支持的所有浏览器都可以使用代码,或者重新调整整个构建过程以使用 Closure,我会选择使用适用于所有浏览器的代码。 - cdmckay
5
我同意尽可能支持多种浏览器,但我拒绝重构我的代码,仅因IE或Edge不完整或“想要与众不同”。有标准可循,如果他们不遵循并且只有少数人支持它,那是他们的问题,这不应影响我们作为Web开发人员的工作。 - David Tabernero M.
3
截至2017年10月,全球支持率为72%,美国支持率为80%。 - Gibolt
显示剩余7条评论

68
var a = A.parentNode.replaceChild(document.createElement("span"), A);

a是被替换的A元素。


2
Bjorn Tipling 的回答实际上是不起作用的。这是 KooiInc 的(正确!)答案,也是正确的评论。现在它可以工作了!;-) 感谢两位! - Pedro Ferreira
9
当然,你肯定可以想出一个除了 A 以外的变量名,哈哈。 - quemeful

7
这个问题很老了,但我发现自己正在为微软认证学习,并且在学习书中建议使用:
oldElement.replaceNode(newElement)

我查了一下,似乎只有IE支持。唉...
我觉得把这个搞笑的小插曲放在这里挺好玩的 ;)

3
最佳方法是使用Element.outerHTML = template;,不需要父元素。
// Get the current element
var currentNode = document.querySelector('#greeting');

// Replace the element
currentNode.outerHTML =
    '<div id="salutations">' +
        '<h1>Hi, universe!</h1>' +
        '<p>The sun is always shining!</p>' +
    '</div>';

3
您可以使用Node.replaceWith(newNode)替换一个HTML元素或节点。
此示例应保留原始节点的所有属性和子元素:
const links = document.querySelectorAll('a')

links.forEach(link => {
  const replacement = document.createElement('span')
  
  // copy attributes
  for (let i = 0; i < link.attributes.length; i++) {
     const attr = link.attributes[i]
     replacement.setAttribute(attr.name, attr.value)
  }
  
  // copy content
  replacement.innerHTML = link.innerHTML
  
  // or you can use appendChild instead
  // link.childNodes.forEach(node => replacement.appendChild(node))

  link.replaceWith(replacement)
})

如果你有以下这些元素:

<a href="#link-1">Link 1</a>
<a href="#link-2">Link 2</a>
<a href="#link-3">Link 3</a>
<a href="#link-4">Link 4</a>

在运行以上代码后,你会得到这些元素:
<span href="#link-1">Link 1</span>
<span href="#link-2">Link 2</span>
<span href="#link-3">Link 3</span>
<span href="#link-4">Link 4</span>

答案假设DOM是静态的。如果DOM已被修改,例如通过onload脚本,那该怎么办? - Page Notes
请确保在DOM被修改或生成后再执行document.querySelectorAll('a') - Nurul Huda

3

我曾经遇到过类似的问题,并在这个讨论中找到了解决方法。使用“替换”操作并没有帮助我解决问题,而根据父元素进行操作又不适合我的情况。使用innerHtml会替换掉子元素,这也不是我想要的结果。最终,使用outerHTML才真正解决了这个问题。希望这个经验能帮助到其他人!

currEl = <div>hello</div>
newElem = <span>Goodbye</span>
currEl.outerHTML = newElem
# currEl = <span>Goodbye</span>

这很聪明,但我不知道它是否符合标准。谢谢! - Thanasis
可能它是全球通用的,我投票认为这个答案是最好的! - Thanasis

2
您可以在创建新元素(createElement)后,使用 replaceChild 替换目标元素的父元素:
const newElement = document.createElement(/*...*/);
const target = document.getElementById("my-table");
target.parentNode.replaceChild(newElement, target);

如果您的新元素的起点是HTML,您可以在父级上使用insertAdjacentHTML然后使用removeChild(或在现代环境中,直接在元素本身上使用remove):
const target = document.getElementById("my-table");
target.insertAdjacentHTML("afterend", theHTMLForTheNewElement);
target.parentNode.removeChild(target); // Or: `target.remove()`

-1

替换LI元素的示例

function (element) {
    let li = element.parentElement;
    let ul = li.parentNode;   
    if (li.nextSibling.nodeName === 'LI') {
        let li_replaced = ul.replaceChild(li, li.nextSibling);
        ul.insertBefore(li_replaced, li);
    }
}

-1

鉴于已经提出的选项,最简单的解决方案是不需要查找父级:

var parent = document.createElement("div");
var child = parent.appendChild(document.createElement("a"));
var span = document.createElement("span");

// for IE
if("replaceNode" in child)
  child.replaceNode(span);

// for other browsers
if("replaceWith" in child)
  child.replaceWith(span);

console.log(parent.outerHTML);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接