JavaScript 中有 insertBefore()
,但是如何在不使用 jQuery 或其他库的情况下插入一个元素 after 另一个元素?
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);
直截了当的 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 { 颜色:绿色; }
existingElement.appendAfter(newElement);
。看看我在这个更新的 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
beforebegin
它是什么? ID?姓名?你应该更具体...
insertAdjacentHTML
+ outerHTML
elementBefore.insertAdjacentHTML('afterEnd', elementAfter.outerHTML)
优点:
DRYer:您不必将前节点存储在变量中并使用它两次。如果您重命名变量,则修改次数较少。
比 insertBefore 打高尔夫球更好(即使现有节点变量名称为 3 个字符长,也会中断)
缺点:
较低的浏览器支持,因为较新:https://caniuse.com/#feat=insert-adjacent
将丢失元素的属性,例如事件,因为 outerHTML 将元素转换为字符串。我们需要它,因为 insertAdjacentHTML 从字符串而不是元素添加内容。
.insertAdjacentElement()
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();
before
和 after
在 MDN 页面上都标记为“实验性”:Experimental. Expect behavior to change in the future.
before
和 after
在 MDN 页面上不再标记为“实验性”:developer.mozilla.org/en-US/docs/Web/API/Element/before developer.mozilla.org/en-US/docs/Web/API/Element/after
快速的 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);
}
}
targetElement.nextSibling
将返回 null
。当使用 null
作为第二个参数调用 node.insertBefore
时,它会将节点添加到集合的末尾。换句话说,if(parent.lastchild == targetElement) {
分支是多余的,因为 parent.insertBefore(newElement, targetElement.nextSibling);
将正确处理所有情况,即使它一开始可能看起来不是这样。许多人已经在其他评论中指出了这一点。
方法 node.after
(doc) 在另一个节点之后插入一个节点。
对于两个 DOM 节点 node1
和 node2
,
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);
实际上,您可以在较新版本的 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 代码进行测试:
上
下
正如预期的那样,它将向上元素移动到向下元素之后
这是我们可以使用 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 可能不是您在 this article 中所述的正确解决方案。
然而,这篇文章写于 2010 年,现在情况可能有所不同。所以自己决定。
JavaScript DOM insertAfter() method @ jsfiddle.net
理想情况下,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);
我知道这个问题已经有太多答案了,但没有一个能满足我的确切要求。
我想要一个与 parentNode.insertBefore
行为完全相反的函数 - 也就是说,它必须接受 null referenceNode
(accepted answer 不接受)并且 insertBefore
将插入这个必须在 start 插入的子节点的 end,否则根本无法使用此函数在开始位置插入;同样的原因 insertBefore
在末尾插入。
由于 null referenceNode
需要您定位父级,因此我们需要知道父级 - insertBefore
是 parentNode
的方法,因此它可以通过这种方式访问父级;我们的函数没有,所以我们需要将父级作为参数传递。
生成的函数如下所示:
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
);
};
}
此代码用于在最后一个现有子项之后插入一个链接项到 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);
您可以使用 appendChild
函数在元素之后插入。
参考:http://www.w3schools.com/jsref/met_node_appendchild.asp
让我们处理所有场景
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);
};
}
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'."));
};
不定期副业成功案例分享
insertBefore()
适用于文本节点。为什么您希望insertAfter()
有所不同?您应该为此创建一对名为insertBeforeElement()
和insertAfterElement()
的单独函数。