闽公网安备 35020302035485号
// 看似简单的移动操作 parent.insertBefore(existingElement, referenceNode);这个行为对普通元素无伤大雅,但对于以下场景却是灾难性的:
5.打开的模态对话框
// 新的原子移动操作 parent.moveBefore(elementToMove, referenceNode);其结合了传统 remove 和 insert 的部分步骤,并新增了以下三个有趣的特性:
3.排队两个连续的变异记录任务:一个用于从旧父节点移除,一个用于插入到新父节点。
| 特性 | insertBefore() | moveBefore() |
|---|---|---|
| 底层操作 | remove() + insert() 组合操作 | 原子移动操作 |
| 元素状态 | 完全重置 | 大部分保留 |
| MutationObserver | 触发 remove + insert 两条记录 | 触发单个 move 记录 |
| 自定义元素 | 触发 disconnectedCallback | 触发 connectedMoveCallback |
| 兼容性 | 全平台支持 | Chrome 133+ |
/* 复杂的动画定义 */
.animation-box {
animation: rotate 3s linear infinite,
scale 2s ease-in-out infinite alternate;
transform-origin: center;
will-change: transform;
}
// 堆代码 duidaima.com
@keyframes rotate {
from { transform: rotate(0deg) scale(1); }
50% { transform: rotate(180deg) scale(1.2); }
to { transform: rotate(360deg) scale(1); }
}
// moveBefore 保持动画连续性
function moveUsingMoveBefore() {
const box = document.getElementById("animatedBox");
targetContainer.moveBefore(box, null);
// 动画保持完全连续,无需重置或重新计算状态
}

用户界面动效:拖拽排序动画、展开/折叠过渡、列表重排动画。
// 传统方式:需要手动保存和恢复状态
function moveUsingInsertBefore() {
const video = document.getElementById("video1");
const currentTime = video.currentTime;
const wasPlaying = !video.paused;
const volume = video.volume;
// 移动操作会重置所有状态
targetContainer.insertBefore(video, referenceNode);
// 需要手动恢复状态
video.currentTime = currentTime;
video.volume = volume;
if (wasPlaying) video.play();
}
// 使用 moveBefore:一行代码解决所有问题
function moveUsingMoveBefore() {
const video = document.getElementById("video2");
targetContainer.moveBefore(video, referenceNode);
// 所有状态自动保持,无需额外代码
}

async function runBenchmark() {
resetMetrics();
// 测试 insertBefore
const insertBeforeStart = performance.now();
await shuffleItems('insertBeforeContainer', false);
const insertBeforeEnd = performance.now();
// 测试 moveBefore
const moveBeforeStart = performance.now();
await shuffleItems('moveBeforeContainer', true);
const moveBeforeEnd = performance.now();
// 更新性能指标
updateMetrics({
insertBefore: {
time: insertBeforeEnd - insertBeforeStart,
reflows: reflows.insertBefore
},
moveBefore: {
time: moveBeforeEnd - moveBeforeStart,
reflows: reflows.moveBefore
}
});
}
