Сохраняйте состояние во время мутаций DOM с помощью moveBefore()

Мы рады объявить о новом API DOM moveBefore() , доступном в Chrome версии 133, который упрощает перемещение элементов в DOM без потери состояния. Продолжайте читать, чтобы узнать, как вы можете использовать его в своих проектах!

Потеря состояния во время мутаций DOM

Используете ли вы API-интерфейс appendChild() для вставки новых элементов в DOM? Многие так делают, но пробовали ли вы когда-нибудь вызвать его — или insertBefore() , или любой другой API вставки, если уж на то пошло — с элементом, который уже находится в DOM? Если это так, вы, возможно, не осознавали, что это незаметно работает, сначала удаляя элемент из его старого родителя и повторно вставляя его в новый. Это потому, что в объектной модели документа есть только примитивы удаления и вставки с тех пор, как в 1998 году был представлен первый проект стандарта DOM. Всякий раз, когда вы думаете, что «перемещаете» что-то в DOM из одного места в другое, вы на самом деле удаляете и вставляем под капот.

Тот факт, что «перемещение» на самом деле является «удалением и вставкой», обычно не влияет на взаимодействие с пользователем. Например, при «перемещении» <p> в DOM эти две операции не имеют разрушительных побочных эффектов, но при перемещении сложных узлов, которые сохраняют важное состояние, таких как элементы <iframe> , элементы в полноэкранном режиме, CSS-анимация и т. д. on — неявная операция «удаления» сбрасывает все виды состояний.

Это может иметь удивительно разрушительные побочные эффекты.

Вы можете увидеть тип состояния, которое сбрасывается, на нашем демонстрационном веб-сайте, сохраняющем состояние , поиграв с перемещениями в дереве DOM. В следующем примере показаны анимации CSS и сброс состояния <iframe> при перемещении элементов из одного родительского контейнера в другой.

Это ограничение может затруднить или даже сделать невозможным создание динамического пользовательского интерфейса. Пользователи расстраиваются и сбиваются с толку, когда состояние приложения загадочным образом сбрасывается, и авторы фреймворков JavaScript несут на себе основную тяжесть этого, тратя бесчисленные часы на перепроектирование своего внешнего кода для решения этой проблемы, создавая сложные библиотеки, такие как MorphDOM , или отправляя отчеты об ошибках, в которых подчеркиваются проблемы, которые они могут решить. т исправить .

Новый API moveBefore()

Мы решили решить эту проблему, добавив в DOM новую примитивную операцию. Его правильно называют примитивом «move», и он доступен разработчикам через новый DOM API moveBefore() .

moveBefore() принимает те же аргументы, что и insertBefore() , но вместо удаления и повторной вставки узлов, когда они уже прикреплены к DOM, этот новый API атомарно перемещает целевой узел в новый родительский узел без сброса большей части состояния . Это, наконец, позволяет разработчикам JavaScript создавать динамические возможности с подвижной анимацией, iframe, полноэкранными элементами и многим другим. Вы можете попробовать это сами, включив экспериментальный флаг chrome://flags/#atomic-move и посетив наш демонстрационный сайт или используя версию 133 Chrome после ее выпуска 4 февраля 2025 года.

Примеры поведения, которых этот новый примитив позволит авторам JavaScript достичь:

  • Сохраняйте состояние воспроизведения видео при навигации пользователя по веб-сайту (независимо от того, предоставлено ли видео из элемента <video> или <iframe> ).
  • Сохраняйте фокус поля пользовательского ввода при его перемещении в DOM.
  • Разрешить плавное завершение анимации при добавлении или удалении нового контента из DOM.
  • Алгоритмы морфинга более высокой точности для согласования существующих DOM с новым контентом.
  • Оставляйте модальные диалоги, всплывающие окна и полноэкранные элементы открытыми.

Мы усердно работаем над внедрением этого API на веб-платформу вместе с другими браузерами и очень рады скоро передать его в руки разработчиков, удовлетворяя многолетние запросы разработчиков и заполняя значительный пробел в веб-платформе.


Как всегда, дайте нам знать, что вы думаете, через Twitter или комментарии ниже, а также сообщайте об ошибках на crbug.com/new .