Giao diện người dùng lớp trên cùng cố định

Tính năng web: moveBefore()

Khi di chuyển một phần tử <dialog>, popover hoặc phần tử toàn màn hình đang mở trong DOM bằng các phương thức truyền thống như appendChild() hoặc insertBefore(), trình duyệt sẽ ngầm xoá phần tử đó khỏi DOM rồi chèn lại. Việc xoá này sẽ đặt lại trạng thái, khiến các cửa sổ phụ, cửa sổ bật lên và phần tử toàn màn hình đang mở đột ngột đóng lại.

Để thay đổi phần tử mẹ của các phần tử lớp trên cùng mà không làm gián đoạn trải nghiệm người dùng hoặc đóng các phần tử đó, hãy sử dụng API moveBefore() nguyên tử.

Đang gán lại phần tử mẹ cho các phần tử lớp trên cùng đang mở

moveBefore() nhận hai đối số: nút cần di chuyển và nút tham chiếu để chèn trước (hoặc null để thêm vào cuối phần tử mẹ mới).

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

Chiến lược dự phòng

Vì moveBefore() là một tính năng cải tiến tăng dần, nên bạn PHẢI sử dụng tính năng phát hiện tính năng trước khi gọi tính năng đó. Đối với các trình duyệt cũ, bạn sẽ phải quay lại phương thức tái gán phần tử mẹ truyền thống.

BẮT BUỘC: Đối với các phần tử <dialog> trong trình duyệt không được hỗ trợ, thao tác di chuyển truyền thống sẽ đóng hộp thoại. Nếu muốn giữ cho kênh luôn mở, bạn phải mở lại kênh theo cách thủ công sau khi di chuyển.

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