Мы рады объявить о новом 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 .