ChatGPT解决这个技术问题 Extra ChatGPT

如何在不使用库的情况下在 JavaScript 中的另一个元素之后插入一个元素?

JavaScript 中有 insertBefore(),但是如何在不使用 jQuery 或其他库的情况下插入一个元素 after 另一个元素?

如果您需要最后一个子节点的特定情况 - stackoverflow.com/questions/5173545/…
@AlanLarimer 太好了。谢谢。你知道 insertAdjacentElement 是什么时候引入的吗?
根据 MDN,IE8 和 Firefox 48(2016 年 8 月 8 日)支持它。跟随线索:bugzilla.mozilla.org/show_bug.cgi?id=811259 --> w3.org/Bugs/Public/show_bug.cgi?id=19962(2016 年 3 月 14 日)

j
johannchopin
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);

其中 referenceNode 是您要放置 newNode 的节点。如果 referenceNode 是其父元素中的最后一个子元素,那很好,因为 referenceNode.nextSibling 将是 null,而 insertBefore 通过添加到列表末尾来处理这种情况。

所以:

function insertAfter(newNode, referenceNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

您可以使用以下代码段对其进行测试:

函数 insertAfter(referenceNode, newNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } var el = document.createElement("span"); el.innerHTML = "测试"; var div = document.getElementById("foo");插入后(div,el);

你好


感谢您提供了一个很好的答案,但是在参数列表中翻转 referenceNode 和 newNode 会不会令人困惑?为什么不遵守 insertBefore 语法?
如果 referenceNode 是最后一个子节点,则此代码片段不处理,它应该在其中 appendChild。
根据 MDN,如果元素是最后一个(因此 nextSibling 为空),则 newNode 将按预期附加
referenceNode.nextElementSibling 是一个更好的选择
@BhumiSinghal:错了。 insertBefore() 适用于文本节点。为什么您希望 insertAfter() 有所不同?您应该为此创建一对名为 insertBeforeElement()insertAfterElement() 的单独函数。
A
Armando

直截了当的 JavaScript 如下:

之前附加:

element.parentNode.insertBefore(newElement, element);

附加后:

element.parentNode.insertBefore(newElement, element.nextSibling);

但是,为了便于使用,可以在其中放置一些原型

通过构建以下原型,您将能够直接从新创建的元素中调用这些函数。

newElement.appendBefore(元素);

newElement.appendAfter(元素);

.appendBefore(element) 原型

Element.prototype.appendBefore = function (element) {
  element.parentNode.insertBefore(this, element);
},false;

.appendAfter(element) 原型

Element.prototype.appendAfter = function (element) {
  element.parentNode.insertBefore(this, element.nextSibling);
},false;

并且,要查看所有内容,请运行以下代码片段

/* 在 NeighborElement 之前添加元素 */ Element.prototype.appendBefore = function(element) { element.parentNode.insertBefore(this, element); }, 错误的; /* 在 NeighborElement 之后添加元素 */ Element.prototype.appendAfter = function(element) { element.parentNode.insertBefore(this, element.nextSibling); }, 错误的; /* 典型的创建和设置一个新的孤立元素对象 */ var NewElement = document.createElement('div'); NewElement.innerHTML = '新元素'; NewElement.id = '新元素'; /* 在使用上述原型之前 - 或 - 之后添加 NewElement */ NewElement.appendAfter(document.getElementById('Neighbor2')); div { 文本对齐:居中; } #Neighborhood { 颜色:棕色; } #NewElement { 颜色:绿色; }

邻居 1
邻居 2
邻居 3

Run it on JSFiddle


extension 函数名称具有误导性。它认为它应该被称为 appendMeBefore 和 appendMeAfter。我认为它像 appendChild() Method 一样使用,例如 existingElement.appendAfter(newElement);。看看我在这个更新的 jsfiddle 中的意思。
Append After 有效,因为如果 element.nextSibling 没有下一个兄弟,nextSibling 为 NULL,然后它会在末尾追加。
我在 jslint 中收到警告:预期的 ';'而是看到','。 }, 错误的;
S
S.Serpooshan

虽然 insertBefore() 很棒并且被这里的大多数答案引用。为了增加灵活性,并且更明确一点,您可以使用:

insertAdjacentElement() as refElem.insertAdjacentElement(position, newElem) 允许您引用任何元素,并将要移动的元素准确插入到您想要的位置(位置可以是以下之一:'beforebegin''afterbegin''beforeend''afterend')如下图:

// refElem.insertAdjacentElement('beforebegin', myElem); 
<p id="refElem">
    // refElem.insertAdjacentElement('afterbegin', myElem);
    ... content ...
    // refElem.insertAdjacentElement('beforeend', myElem);
</p>
// refElem.insertAdjacentElement('afterend', myElem); 

其他类似用例要考虑的:insertAdjacentHTML()insertAdjacentText()

参考:

https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentText


真的应该给这个答案一些爱,这是快速接近 2020 年代的现代方法。
这个答案怎么埋得这么深?我将奖励它一些分数以引起更多关注。
一点旁注,它不适用于文档片段。
beforebegin 它是什么? ID?姓名?你应该更具体...
C
Ciro Santilli Путлер Капут 六四事

insertAdjacentHTML + outerHTML

elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)

优点:

DRYer:您不必将前节点存储在变量中并使用它两次。如果您重命名变量,则修改次数较少。

比 insertBefore 打高尔夫球更好(即使现有节点变量名称为 3 个字符长,也会中断)

缺点:

较低的浏览器支持,因为较新:https://caniuse.com/#feat=insert-adjacent

将丢失元素的属性,例如事件,因为 outerHTML 将元素转换为字符串。我们需要它,因为 insertAdjacentHTML 从字符串而不是元素添加内容。


如果您已经构建了元素,则可以使用 .insertAdjacentElement()
截至 2018 年,浏览器支持看起来相当稳固:caniuse.com/#feat=insert-adjacent
这是一个不错的解决方案,我建议每个人都阅读此xahlee.info/js/js_insert_after.html
M
Mister SirCode

2018 解决方案(Bad Practice,转到 2020)

我知道这个问题很古老,但对于任何未来的用户来说,这是一个修改过的原型。这只是不存在的 .insertAfter 函数的 polyfill。此原型直接将函数 HTMLElement.insertAfter(element); 添加到 HTMLElement Prototype:

// Parent
const el = document.body;
// New Element
const newEl = document.createElement("div");

// Custom Method
Element.prototype.insertAfter = function(new) {
    this.parentNode.insertBefore(new, this.nextSibling);
}

// Insert Before Element
el.insertBefore(newEl)

// Insert After Element
el.insertAfter(newEl);

// Just remember you cant use .insertAfter() or .insertBefore() 
// after either is already called.
// You cant place one element in two places at once.

2019解决方案(丑陋/过时,去2020)

不要使用原型(如 2018 解决方案)。覆盖原型既危险又低质量。如果您想要一个新方法,请改用函数覆盖。如果您想要商业项目的安全功能,只需使用默认功能。它不那么漂亮,但它有效:

// Parent
const el = document.body;
// New Element
const newEl = document.createElement("div");

// Function You Need
function insertAfter(el0, el1) {
    el0.parentNode.insertBefore(el1, el0.nextSibling);
}

// Insert Before Element
el.insertBefore(newEl);

// Insert After Element
insertAfter(el, newEl);

// Just remember you cant use insertAfter() or .insertBefore()
// after either is already called.
// You cant place one element in two places at once.

2020 解决方案 - ChildNode

ChildNode 的当前 Web 标准:MDN Docs - ChildNode

它目前处于生活标准中,可以安全使用。

对于不受支持的浏览器(例如 IE),请使用此 Polyfill:https://github.com/seznam/JAK/blob/master/lib/polyfills/childNode.js

当我说它们是不好的做法时,我意识到 polyfill 使用了 Proto Overrides。它们是,特别是当它们被盲目使用时,就像我的第一个解决方案一样。但是,MDN 文档中的 polyfill 使用了一种初始化和执行形式,与仅覆盖原型相比,这种形式更加可靠和安全。

如何使用子节点:

// Parent 
const el = document.body;
// New Element
const newEl = document.createElement("div");

// Insert Before Element
el.before(newEl);

// Insert After Element
el.after(newEl);

// Just remember you cant use .after() or .before()
// after either is already called.
// You cant place one element in two places at once.

// Another feature of ChildNode is the .remove() method,
// which deletes the element from the DOM
el.remove();
newEl.remove();

关于“2020 解决方案”:beforeafter 在 MDN 页面上都标记为“实验性”:Experimental. Expect behavior to change in the future.
@izogfif 好吧,考虑到它刚刚进入生活水平,这是意料之中的。我非常怀疑他们会显着改变该方法的行为以适应新标准。如果他们这样做,我将编辑答案。 MDN 文档上的唯一原因很可能是因为它最近被添加到生活标准中,所以它仍然是“实验性的”,即使它稳定并且在当前版本中
它运行良好。完全支持除 IE。
@Mircea 如果您希望它在 IE 上运行,请使用我的回答中建议的 polyfill。 (虽然老实说,我怀疑有人真的关心 IE 了,我个人不再支持它了)
B
Brian Peacock

快速的 Google 搜索显示this script

// create function, it expects 2 values.
function insertAfter(newElement,targetElement) {
    // target is what you want it to go after. Look for this elements parent.
    var parent = targetElement.parentNode;

    // if the parents lastchild is the targetElement...
    if (parent.lastChild == targetElement) {
        // add the newElement after the target element.
        parent.appendChild(newElement);
    } else {
        // else the target has siblings, insert the new element between the target and it's next sibling.
        parent.insertBefore(newElement, targetElement.nextSibling);
    }
}

对于偶然发现此脚本的任何人,我不建议使用它。它试图解决@karim79 的本机解决方案已经解决的问题。他的脚本更快、更高效——我强烈建议使用该脚本而不是这个脚本。
作为 JavaScript 中的一般经验法则,浏览器可以比您编写的任何内容更快地完成任务。虽然这两种解决方案在功能上是相同的,但我的 JavaScript 解决方案需要先被浏览器读取并理解才能使用,并且每次执行时都需要额外检查。 karim79 提供的解决方案将在内部完成所有这些工作,从而节省这些步骤。差异充其量是微不足道的,但他的解决方案是更好的解决方案。
换句话说,它试图解决一个不存在的问题。额外检查本身并没有错,但我认为它并没有传播对这些方法的最佳理解
差不多。我将脚本留在这里是因为这是我以前写的那种东西,但公认的答案更好,显示对方法的更好理解并且速度更快。没有理由改用这个答案 - 我什至不确定为什么它仍然会得到支持
如果 targetElement 是其兄弟元素中的最后一个元素,则 targetElement.nextSibling 将返回 null。当使用 null 作为第二个参数调用 node.insertBefore 时,它会将节点添加到集合的末尾。换句话说,if(parent.lastchild == targetElement) { 分支是多余的,因为 parent.insertBefore(newElement, targetElement.nextSibling); 将正确处理所有情况,即使它一开始可能看起来不是这样。许多人已经在其他评论中指出了这一点。
g
golopot

方法 node.after (doc) 在另一个节点之后插入一个节点。

对于两个 DOM 节点 node1node2

node1.after(node2)node1 之后插入 node2

此方法在旧版浏览器中不可用,因此通常需要使用 polyfill。


不过,这需要一些手动工作才能实现为功能 insertAfter,所以不幸的是,我认为这不能正常工作。
R
Rob Porter

或者您可以简单地执行以下操作:

referenceNode.parentNode.insertBefore( newNode, referenceNode )
referenceNode.parentNode.insertBefore( referenceNode, newNode )

我不会想到这种方法。我更喜欢使用@karim79 的more direct answer,但请记住这一点。
我不建议这样做,但为创造力+1。
M
Malik Khalil

步骤 1. 准备元素:

var element = document.getElementById('ElementToAppendAfter');
var newElement = document.createElement('div');
var elementParent = element.parentNode;

步骤 2. 附加在 :

elementParent.insertBefore(newElement, element.nextSibling);

A
Anime no Sekai

实际上,您可以在较新版本的 Chrome、Firefox 和 Opera 中使用名为 after() 的方法。这种方法的缺点是 Internet Explorer 还不支持它。

例子:

// You could create a simple node
var node = document.createElement('p')

// And then get the node where you want to append the created node after
var existingNode = document.getElementById('id_of_the_element')

// Finally you can append the created node to the exisitingNode
existingNode.after(node)

一个简单的 HTML 代码进行测试:

正如预期的那样,它将向上元素移动到向下元素之后


P
Payel Dutta

这是我们可以使用 vanilla javascript 在另一个元素之后添加元素的最简单方法

var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');

参考:https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML


并不真地。这附加到结尾或开头,而不是在另一个元素之后。
@MartinJames 它实际上确实附加在另一个元素之后。有四种可能的 insertPosition: beforebegin - 在当前节点之前插入元素 beforeend - 将元素追加到当前节点的末尾。所以元素在开始之后成为当前节点的最后一个子节点 - 将元素添加到当前节点的开头。所以元素成为当前节点后的第一个子节点 - 在当前节点之后插入元素。所以元素成为当前节点的nextSibling
D
Dmytro Dzyubak

insertBefore() 方法的使用与 parentNode.insertBefore() 类似。所以要模仿这个并创建一个方法parentNode.insertAfter(),我们可以编写以下代码。

JavaScript

Node.prototype.insertAfter = function(newNode, referenceNode) {
    return referenceNode.parentNode.insertBefore(
        newNode, referenceNode.nextSibling); // based on karim79's solution
};

// getting required handles
var refElem = document.getElementById("pTwo");
var parent = refElem.parentNode;

// creating <p>paragraph three</p>
var txt = document.createTextNode("paragraph three");
var paragraph = document.createElement("p");
paragraph.appendChild(txt);

// now we can call it the same way as insertBefore()
parent.insertAfter(paragraph, refElem);

HTML

<div id="divOne">
    <p id="pOne">paragraph one</p>
    <p id="pTwo">paragraph two</p>
</div>

请注意,扩展 DOM 可能不是您在 this article 中所述的正确解决方案。

然而,这篇文章写于 2010 年,现在情况可能有所不同。所以自己决定。

JavaScript DOM insertAfter() method @ jsfiddle.net


D
Darlesson

理想情况下,insertAfter 应该类似于 insertBefore。下面的代码将执行以下操作:

如果没有子节点,则追加新节点

如果没有引用节点,则追加新节点

如果引用Node之后没有Node,则追加新Node

如果引用节点之后有兄弟节点,则在该兄弟节点之前插入新节点

返回新节点

扩展 Node

Node.prototype.insertAfter = function(node, referenceNode) {

    if (node)
        this.insertBefore(node, referenceNode && referenceNode.nextSibling);

    return node;
};

一个常见的例子

node.parentNode.insertAfter(newNode, node);

查看运行的代码

// 首先扩展 Node.prototype.insertAfter = function(node, referenceNode) { if (node) this.insertBefore(node, referenceNode && referenceNode.nextSibling);返回节点; };变量参考节点,新节点; newNode = document.createElement('li') newNode.innerText = '第一个新项目'; newNode.style.color = '#FF0000'; document.getElementById('no-children').insertAfter(newNode); newNode = document.createElement('li'); newNode.innerText = '第二个新项目'; newNode.style.color = '#FF0000'; document.getElementById('no-reference-node').insertAfter(newNode); referenceNode = document.getElementById('no-sibling-after'); newNode = document.createElement('li'); newNode.innerText = '第三个新项目'; newNode.style.color = '#FF0000'; referenceNode.parentNode.insertAfter(newNode, referenceNode); referenceNode = document.getElementById('sibling-after'); newNode = document.createElement('li'); newNode.innerText = '第四个新项目'; newNode.style.color = '#FF0000'; referenceNode.parentNode.insertAfter(newNode, referenceNode);

没有孩子
    没有参考节点
    • 第一项
    后无同级
    • 第一项
    后同级
    h5>
    • 第一项
    • 第三项


    m
    mindplay.dk

    我知道这个问题已经有太多答案了,但没有一个能满足我的确切要求。

    我想要一个与 parentNode.insertBefore 行为完全相反的函数 - 也就是说,它必须接受 null referenceNodeaccepted answer 不接受)并且 insertBefore 将插入这个必须在 start 插入的子节点的 end,否则根本无法使用此函数在开始位置插入;同样的原因 insertBefore 在末尾插入。

    由于 null referenceNode 需要您定位父级,因此我们需要知道父级 - insertBeforeparentNode 的方法,因此它可以通过这种方式访问父级;我们的函数没有,所以我们需要将父级作为参数传递。

    生成的函数如下所示:

    function insertAfter(parentNode, newNode, referenceNode) {
      parentNode.insertBefore(
        newNode,
        referenceNode ? referenceNode.nextSibling : parentNode.firstChild
      );
    }
    

    或者(如果必须,我不推荐)您当然可以增强 Node 原型:

    if (! Node.prototype.insertAfter) {
      Node.prototype.insertAfter = function(newNode, referenceNode) {
        this.insertBefore(
          newNode,
          referenceNode ? referenceNode.nextSibling : this.firstChild
        );
      };
    }
    

    e
    eQ19

    此代码用于在最后一个现有子项之后插入一个链接项到 inlining 一个小 css 文件

    var raf, cb=function(){
        //create newnode
        var link=document.createElement('link');
        link.rel='stylesheet';link.type='text/css';link.href='css/style.css';
    
        //insert after the lastnode
        var nodes=document.getElementsByTagName('link'); //existing nodes
        var lastnode=document.getElementsByTagName('link')[nodes.length-1]; 
        lastnode.parentNode.insertBefore(link, lastnode.nextSibling);
    };
    
    //check before insert
    try {
        raf=requestAnimationFrame||
            mozRequestAnimationFrame||
            webkitRequestAnimationFrame||
            msRequestAnimationFrame;
    }
    catch(err){
        raf=false;
    }
    
    if (raf)raf(cb); else window.addEventListener('load',cb);
    

    D
    Doug LN

    您可以使用 appendChild 函数在元素之后插入。

    参考:http://www.w3schools.com/jsref/met_node_appendchild.asp


    此解决方案不适用于 2 p 标签。您不能使用此功能在另一个 p 标签之后添加 ap 标签。
    S
    Sami

    让我们处理所有场景

     function insertAfter(newNode, referenceNode) {
            if(referenceNode && referenceNode.nextSibling && referenceNode.nextSibling.nodeName == '#text')
                referenceNode = referenceNode.nextSibling;
    
            if(!referenceNode)
                document.body.appendChild(newNode);
            else if(!referenceNode.nextSibling)
                document.body.appendChild(newNode);
            else            
                referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);            
        }
    

    y
    yavuzkavus
    if( !Element.prototype.insertAfter ) {
        Element.prototype.insertAfter = function(item, reference) {
            if( reference.nextSibling )
                reference.parentNode.insertBefore(item, reference.nextSibling);
            else
                reference.parentNode.appendChild(item);
        };
    }
    

    B
    Boiethios

    insertAfter 的健壮实现。

    // source: https://github.com/jserz/domPlus/blob/master/src/insertAfter()/insertAfter.js
    Node.prototype.insertAfter = Node.prototype.insertAfter || function (newNode, referenceNode) {
      function isNode(node) {
        return node instanceof Node;
      }
    
      if(arguments.length < 2){
        throw(new TypeError("Failed to execute 'insertAfter' on 'Node': 2 arguments required, but only "+ arguments.length +" present."));
      }
    
      if(isNode(newNode)){
        if(referenceNode === null || referenceNode === undefined){
          return this.insertBefore(newNode, referenceNode);
        }
    
        if(isNode(referenceNode)){
          return this.insertBefore(newNode, referenceNode.nextSibling);
        }
    
        throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 2 is not of type 'Node'."));
      }
    
      throw(new TypeError("Failed to execute 'insertAfter' on 'Node': parameter 1 is not of type 'Node'."));
    };
    

    添加一些解释,说明此答案如何帮助 OP 解决当前问题
    运行上面的代码,就可以在指定的referenceNode后面插入一个newNode。