語法
moveBefore(movedNode, referenceNode)
引數
movedNode-
一個
Node,表示要移動的節點。請注意,這必須是一個Element或CharacterData節點。 referenceNode-
一個
Node,movedNode將被移動到此節點之前;或者為null。如果值為null,movedNode將插入到呼叫節點的子節點的末尾。
返回值
無(undefined)。
異常
HierarchyRequestErrorTypeError-
在以下任何情況下丟擲:
- 指定的
movedNode不屬於 DOM,但你試圖將其移動到屬於 DOM 的節點內部,反之亦然。 - 指定的
movedNode是正在呼叫moveBefore()的 Element 的祖先。 - 你試圖在兩個不同的文件之間移動
movedNode。 - 指定的
movedNode不是Element或CharacterData節點。
- 指定的
NotFoundErrorTypeError-
指定的
referenceNode不是你正在呼叫moveBefore()的節點的子節點,即你試圖將movedNode移動到的節點。 TypeErrorTypeError-
未提供第二個引數。
描述
moveBefore() 方法將給定節點移動到 DOM 中的新位置。它提供了與 Node.insertBefore() 方法類似的功能,不同之處在於它不會先移除再重新插入節點。這意味著節點的狀態(如果使用 insertBefore() 和類似機制移動節點,其狀態會重置)在移動後會保留。這包括:
和 元素的播放狀態不包含在上述列表中,因為這些元素在被移除和重新插入時會保留其狀態,無論使用何種機制。
當使用 MutationObserver 觀察 DOM 變化時,使用 moveBefore() 移動的節點將被記錄為 已移除節點 和 已新增節點。
moveBefore() 約束
使用 moveBefore() 時需要注意一些約束:
- 它只能在同一個文件中移動節點時工作。
- 如果你嘗試將未連線到 DOM 的節點移動到已連線的父節點中,或反之,它將不起作用。
在這種情況下,moveBefore() 將丟擲 HierarchyRequestError 異常。如果上述約束是你的特定用例的要求,你應該改用 Node.insertBefore(),或者使用 try...catch 來處理因此類情況引起的錯誤。
移動自定義元素並保留狀態
每次自定義元素在 DOM 中的位置透過 Element.moveBefore() 或類似方法(如 Node.insertBefore())更新時,其 disconnectedCallback() 和 connectedCallback() 生命週期回撥都會被觸發。由於這些回撥通常用於實現在元素生命週期開始或結束時執行的任何必需的初始化或清理程式碼,因此在移動元素(而不是移除或插入)時執行它們可能會導致其狀態出現問題。
你可以使用 connectedMoveCallback() 回撥來保留自定義元素的狀態。當使用 moveBefore() 移動自定義元素時,將執行 connectedMoveCallback() 而不是 connectedCallback() 和 disconnectedCallback()。
有關更多資訊,請參閱移動自定義元素。
示例
moveBefore() 的基本用法
在此演示中,我們演示了 moveBefore() 的基本用法。
HTML
HTML 包含一個 我們為盒子的外觀、感覺和間距提供了一些基本的樣式,並使用 Flexbox 來居中其內容。 在我們的指令碼中,我們透過 渲染後的示例如下所示: 嘗試點選 在此演示中,我們提供了多種機制來移動包含 YouTube 嵌入的 HTML 包含一個 我們使用 Flexbox 進行佈局,使兩個 在我們的指令碼中,我們透過 渲染後的示例如下所示: 嘗試播放 YouTube 嵌入,然後點選每個 載入中… 元素,其中包含一個 元素。,我們稍後將使用它來移動 <article id="wrapper">
<div id="mover">
<button>Move me!</button>
</div>
<section id="section1">
<h2>Section 1</h2>
</section>
<section id="section2">
<h2>Section 2</h2>
</section>
</article>
CSS
#section1,
#section2,
#mover {
width: 200px;
height: 80px;
border: 5px solid rgb(0 0 0 / 0.25);
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
}
#section1,
#section2 {
background-color: hotpink;
}
#mover {
background-color: orange;
}
JavaScript
addEventListener() 為 附加了一個點選事件監聽器。當按鈕被點選時,我們檢查 mover nextElementSibling 是否是第一個 元素。如果是,我們對 wrapper 呼叫 moveBefore(),並指定將 之前。如果不是,我們使用 moveBefore() 將 之前。
const wrapper = document.getElementById("wrapper");
const section1 = document.getElementById("section1");
const section2 = document.getElementById("section2");
const mover = document.getElementById("mover");
const moveBtn = document.querySelector("button");
moveBtn.addEventListener("click", () => {
if (mover.nextElementSibling === section1) {
wrapper.moveBefore(mover, section2);
} else {
wrapper.moveBefore(mover, section1);
}
});
結果
幾次,注意它是如何在兩個位置之間切換的。演示狀態保留
moveBefore() 如何保留嵌入的播放狀態,而其他機制則不保留。
HTML
元素,其中包含兩個 元素。第一個 元素包含一個 元素,我們稍後將新增功能,透過 JavaScript 在部分之間移動嵌入的 <article id="wrapper">
<section id="section1">
<div id="mover">
<iframe
width="300"
height="200"
src="https://www.youtube.com/embed/XvoENpR9cCQ?si=o2i6MvxugD-O5yyv"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>
</div>
</section>
<section id="section2"></section>
</article>
<div id="controls">
<button id="move-before">move with <code>moveBefore()</code></button>
<button id="insertbefore">move with <code>insertBefore()</code></button>
<button id="prepend">move with <code>prepend()</code></button>
</div>
CSS
元素並排顯示,並使按鈕在 controls #wrapper,
#controls {
width: 100%;
display: flex;
}
#wrapper {
margin-bottom: 10px;
}
section {
flex: 1;
padding: 10px;
}
#controls {
display: flex;
justify-content: space-around;
}
#section1 {
background-color: hotpink;
}
#section2 {
background-color: orange;
}
#mover {
max-width: 100%;
background-color: black;
}
JavaScript
addEventListener() 為每個 附加 click 事件監聽器。當按鈕被點選時,我們檢查哪個 元素是我們的嵌入 parentElement,然後使用相關函式(moveBefore()、insertBefore() 或 prepend())將其移動到另一個 元素內部。
const section1 = document.getElementById("section1");
const section2 = document.getElementById("section2");
const mover = document.getElementById("mover");
const moveBeforeBtn = document.getElementById("move-before");
const insertbeforeBtn = document.getElementById("insertbefore");
const prependBtn = document.getElementById("prepend");
moveBeforeBtn.addEventListener("click", () => {
if (mover.parentElement === section1) {
section2.moveBefore(mover, null);
} else {
section1.moveBefore(mover, null);
}
});
insertbeforeBtn.addEventListener("click", () => {
if (mover.parentElement === section1) {
section2.insertBefore(mover, null);
} else {
section1.insertBefore(mover, null);
}
});
prependBtn.addEventListener("click", () => {
if (mover.parentElement === section1) {
section2.prepend(mover);
} else {
section1.prepend(mover);
}
});
結果
幾次,以將 insertBefore() 和 prepend() 的情況下,嵌入狀態在每次移動後都會重置,因此需要重新啟動。然而,在使用 moveBefore() 的情況下,狀態在每次移動後都會保留。
規範
規範
DOM
# dom-parentnode-movebefore瀏覽器相容性
另見