繁体   English   中英

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

[英]How to insert an element after another element in JavaScript without using a library?

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

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

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

所以:

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

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

 function insertAfter(referenceNode, newNode) { referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling); } var el = document.createElement("span"); el.innerHTML = "test"; var div = document.getElementById("foo"); insertAfter(div, el);
 <div id="foo">Hello</div>

简单的 JavaScript 如下:

之前追加:

element.parentNode.insertBefore(newElement, element);

之后追加:

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

但是,为了便于使用,在那里扔了一些原型

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

  • newElement.appendBefore(element);

  • newElement.appendAfter(element);

.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;

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

 /* Adds Element BEFORE NeighborElement */ Element.prototype.appendBefore = function(element) { element.parentNode.insertBefore(this, element); }, false; /* Adds Element AFTER NeighborElement */ Element.prototype.appendAfter = function(element) { element.parentNode.insertBefore(this, element.nextSibling); }, false; /* Typical Creation and Setup A New Orphaned Element Object */ var NewElement = document.createElement('div'); NewElement.innerHTML = 'New Element'; NewElement.id = 'NewElement'; /* Add NewElement BEFORE -OR- AFTER Using the Aforementioned Prototypes */ NewElement.appendAfter(document.getElementById('Neighbor2'));
 div { text-align: center; } #Neighborhood { color: brown; } #NewElement { color: green; }
 <div id="Neighborhood"> <div id="Neighbor1">Neighbor 1</div> <div id="Neighbor2">Neighbor 2</div> <div id="Neighbor3">Neighbor 3</div> </div>

在 JSFiddle 上运行它

尽管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

insertAdjacentHTML + outerHTML

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

优点:

  • DRYer:您不必将 before 节点存储在变量中并使用它两次。 如果您重命名变量,则修改的次数较少。
  • 打高尔夫球比insertBefore (即使现有节点变量名称为 3 个字符长,也不会中断)

缺点:

  • 较新的浏览器支持较低: https : //caniuse.com/#feat=insert-adjacent
  • 将丢失元素的属性,例如事件,因为outerHTML将元素转换为字符串。 我们需要它是因为insertAdjacentHTML从字符串而不是元素添加内容。

快速谷歌搜索揭示了 这个脚本

// 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);
    }
}

2018 年解决方案(不良做法,转到 2020 年)

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

// 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 解决方案)。 覆盖原型既危险又低质量。 如果您想要一个新方法,请改用 Function Overrides。
如果您想要商业项目的安全功能,只需使用默认功能。 它不那么漂亮,但它有效:

// 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 文档 - 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();

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

对于两个 DOM 节点node1node2

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

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

或者你可以简单地做:

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

步骤 1. 准备元素:

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

步骤 2. 在 之后追加:

elementParent.insertBefore(newElement, element.nextSibling);

这是我们可以使用 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

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可能不适合你的解决方案中所述 这篇文章

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

JavaScript DOM insertAfter() 方法@jsfiddle.net

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

  • 如果没有子Node则附加新Node
  • 如果没有引用Node ,则追加新的Node
  • 如果没有Node参考后Node ,新Node追加
  • 如果引用Node有一个兄弟Node ,那么新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);

查看运行的代码

 // First extend Node.prototype.insertAfter = function(node, referenceNode) { if (node) this.insertBefore(node, referenceNode && referenceNode.nextSibling); return node; }; var referenceNode, newNode; newNode = document.createElement('li') newNode.innerText = 'First new item'; newNode.style.color = '#FF0000'; document.getElementById('no-children').insertAfter(newNode); newNode = document.createElement('li'); newNode.innerText = 'Second new item'; newNode.style.color = '#FF0000'; document.getElementById('no-reference-node').insertAfter(newNode); referenceNode = document.getElementById('no-sibling-after'); newNode = document.createElement('li'); newNode.innerText = 'Third new item'; newNode.style.color = '#FF0000'; referenceNode.parentNode.insertAfter(newNode, referenceNode); referenceNode = document.getElementById('sibling-after'); newNode = document.createElement('li'); newNode.innerText = 'Fourth new item'; newNode.style.color = '#FF0000'; referenceNode.parentNode.insertAfter(newNode, referenceNode);
 <h5>No children</h5> <ul id="no-children"></ul> <h5>No reference node</h5> <ul id="no-reference-node"> <li>First item</li> </ul> <h5>No sibling after</h5> <ul> <li id="no-sibling-after">First item</li> </ul> <h5>Sibling after</h5> <ul> <li id="sibling-after">First item</li> <li>Third item</li> </ul>

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

我想要一个与parentNode.insertBefore行为完全相反的函数——也就是说,它必须接受一个空的referenceNode接受的答案没有),并且insertBefore将在子节点的末尾插入,这个必须在开头插入, 因为否则根本无法使用此函数在开始位置插入; 同样的原因insertBefore在最后插入。

由于空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
    );
  };
}

您实际上可以在较新版本的 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 代码来测试它是:

 <!DOCTYPE html> <html> <body> <p id='up'>Up</p> <p id="down">Down</p> <button id="switchBtn" onclick="switch_place()">Switch place</button> <script> function switch_place(){ var downElement = document.getElementById("down") var upElement = document.getElementById("up") downElement.after(upElement); document.getElementById('switchBtn').innerHTML = "Switched!" } </script> </body> </html>

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

我使用以下代码在 select 的末尾插入选项。只需将 null 作为第二个参数传递。 我不确定这是否是“选择”元素的异常,因为我从未在其他任何东西上尝试过,但如果有人来这里寻找这个,可能会有所帮助。 也适用于 IE(令人惊讶)。 :)

            var x = document.getElementById("SELECT_LIST");
            var boption = document.createElement("option");
            boption.text = "SOME TEXT";
            boption.value = "SOME VALUE";
            x.insertBefore(boption, null);

此代码用于在最后一个现有子项之后插入一个链接项以内联一个小的 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);
 <!DOCTYPE html>
 <html lang="ca">
 <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <script>
        function createDiv(){
            var newDiv = document.createElement("div");
            var txt = document.createTextNode("I'm the second div");
            newDiv.appendChild(txt);
            var x = document.getElementsByTagName("BODY")[0];
            x.insertBefore(newDiv, third);
        }
    </script>
</head>
<body>
    <div class="first">
        <p>
            I'm the first div
        </p>
    </div>
    <div id="third">
        <p>
            I'm the third div
        </p>
    </div>
    <button type= " button " name= " button " onclick = " createDiv() " >
        Create the second Div
    </button>
</body>
</html>

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

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

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'."));
};

让我们处理所有场景

 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);            
    }
if( !Element.prototype.insertAfter ) {
    Element.prototype.insertAfter = function(item, reference) {
        if( reference.nextSibling )
            reference.parentNode.insertBefore(item, reference.nextSibling);
        else
            reference.parentNode.appendChild(item);
    };
}

嗨,请看一下如何在 JavaScript 中向 HTML DOM 添加新元素?<\/a>

<html> 
<head> 
<title>t1</title> 
<script type="text/javascript"> 
    function addNode() 
     {var newP = document.createElement("p"); 
      var textNode = document.createTextNode(" This is a new text node"); 
      newP.appendChild(textNode);
      document.getElementById("firstP").appendChild(newP); } 
</script> </head> 
<body> <p id="firstP">firstP<p> </body> 
</html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM