Web 功能:
moveBefore()
使用 appendChild() 或 insertBefore() 等传统方法在 DOM 中移动打开的 <dialog>、popover 或全屏元素时,浏览器会隐式地从 DOM 中移除该元素,然后重新插入。此移除操作会重置状态,导致打开的模态窗口、弹出式窗口和全屏元素突然关闭。
如需在不中断用户体验或不关闭顶层元素的情况下重新设置其父级,请改用原子 moveBefore() API。
重新设置打开的顶层元素的父级
moveBefore() 接受两个参数:要移动的节点,以及要在其前面插入的参考节点(或 null,用于附加到新父节点的末尾)。
const newParent = document.getElementById('new-container');
const dialogElement = document.getElementById('my-dialog');
// MANDATORY: Use moveBefore to ensure the <dialog> or popover stays open.
// Passing null appends it to the end of newParent.
newParent.moveBefore(dialogElement, null);
后备策略
由于 moveBefore() 是一项渐进增强功能,因此您必须先使用功能检测,然后再调用它。对于旧版浏览器,您必须回退到传统的重定父级。
强制性:对于不受支持的浏览器中的 <dialog> 元素,传统移动操作会关闭对话框。如果您需要保持其打开状态,则必须在移动后手动重新打开。
const targetParent = document.getElementById('target-container');
const popoverOrDialog = document.getElementById('my-top-layer-element');
// Check if moveBefore is supported
if ('moveBefore' in Element.prototype) {
targetParent.moveBefore(popoverOrDialog, null);
} else {
// Fallback: traditional move.
// Note: This WILL close <dialog>, popover, and fullscreen elements.
const wasOpen = popoverOrDialog.hasAttribute('open') || popoverOrDialog.matches(':popover-open');
targetParent.insertBefore(popoverOrDialog, null);
// Manually restore state if possible
if (wasOpen && typeof popoverOrDialog.showModal === 'function') {
popoverOrDialog.showModal();
} else if (wasOpen && typeof popoverOrDialog.showPopover === 'function') {
popoverOrDialog.showPopover();
}
}