Z przyjemnością informujemy, że w Chrome w wersji 133 dostępny jest nowy interfejs DOM API moveBefore()
, który ułatwia przenoszenie elementów w DOM bez utraty stanu. Czytaj dalej, aby dowiedzieć się, jak możesz go używać w swoich projektach.
Utrata stanu podczas mutacji DOM
Czy do wstawiania nowych elementów do DOM używasz interfejsu API appendChild()
? Wiele osób ma ten problem, ale czy kiedykolwiek próbowałeś wywołać go (lub insertBefore()
, albo dowolnego innego interfejsu API do wstawiania) za pomocą elementu, który znajduje się już w DOM? W takim przypadku możesz nie wiedzieć, że ta funkcja działa po cichu, najpierw usuwając element ze starego elementu nadrzędnego, a następnie wstawiając go w nowym. Dzieje się tak, ponieważ od czasu wprowadzenia pierwszego projektu standardu DOM w 1998 r. model obiektowy dokumentu zawierał tylko prymitywne operacje usuwania i wklejania. Gdy wydaje Ci się, że coś „przesuwasz” w DOM z jednego miejsca do drugiego, tak naprawdę usuwasz i wstawiasz elementy.
Fakt, że „przesuwanie” jest w istocie „usuwaniem i wstawianiem”, zwykle nie ma wpływu na wrażenia użytkownika. Na przykład podczas „przemieszczania” elementu <p>
w DOM-ie te dwie operacje nie mają żadnych zakłócających skutków ubocznych, ale podczas przemieszczania złożonych węzłów, które zawierają istotne stany, takich jak elementy <iframe>
, elementy w trybie pełnoekranowym, animacje CSS itp., operacja domyślnego „usunięcia” powoduje zresetowanie wszystkich stanów.
Może to mieć zaskakująco niekorzystne skutki uboczne.
Aby zobaczyć, jaki stan jest resetowany w naszej witrynie demonstracyjnej z zachowaniem stanu, możesz poeksperymentować z przesunięciami w drzewie DOM. Ten przykład pokazuje animacje CSS i stan <iframe>
resetowany podczas przenoszenia elementów z jednego kontenera nadrzędnego do drugiego.
To ograniczenie może utrudniać, a nawet uniemożliwiać tworzenie dynamicznych treści. Użytkownicy są sfrustrowani i zdezorientowani, gdy stan aplikacji jest tajemniczo resetowany, a twórcy frameworków JavaScript muszą poświęcić niezliczone godziny na przeprojektowanie kodu po stronie klienta, aby rozwiązać ten problem, tworząc złożone biblioteki, takie jak MorphDOM, lub zajmować się raportami o błędach, które wykazują problemy, których nie można rozwiązać.
Nowy interfejs API moveBefore()
Aby rozwiązać ten problem, dodaliśmy do DOM nową operację prymitywną. Jest to odpowiednio nazwany prymityw „move” i jest udostępniany deweloperom za pomocą nowego interfejsu DOM moveBefore()
API.
Funkcja moveBefore()
przyjmuje te same argumenty co funkcja insertBefore()
, ale zamiast usuwania i ponownie wstawiania węzłów, gdy są one już dołączone do DOM, nowy interfejs API przenosi je w sposób automatyczny do nowego elementu nadrzędnego bez resetowania większości stanu. Dzięki temu deweloperzy JavaScripta mogą tworzyć dynamiczne treści z animowanymi elementami, ramkami iframe i elementami na pełnym ekranie. Możesz to sprawdzić samodzielnie, włączając flagę eksperymentalną chrome://flags/#atomic-move
i otwierając naszą stronę demonstracyjną lub używając wersji 133 Chrome po jej wydaniu 4 lutego 2025 r.
Przykłady zachowań, które ten nowy element umożliwi autorom JavaScriptu:
- Zachowanie stanu odtwarzania filmu podczas poruszania się użytkownika po witrynie (niezależnie od tego, czy film jest udostępniany z elementu
<video>
czy<iframe>
). - Zachowywanie pola wprowadzania danych użytkownika w centrum uwagi podczas jego przenoszenia w DOM.
- Dopuszczaj płynne zakończenie animacji podczas dodawania lub usuwania nowych treści z DOM.
- Algorytmy tworzenia przejść o wyższej jakości do porównywania dotychczasowych DOM-ów z nowymi treściami.
- Nie zamykaj okien modalnych, wyskakujących ani elementów pełnoekranowych.
Pracujemy nad wprowadzeniem tego interfejsu API na platformę internetową w innych przeglądarkach. Cieszymy się, że wkrótce udostępnimy go deweloperom, spełniając ich wieloletnie oczekiwania i zamykając ważną lukę w platformie internetowej.
Jak zawsze przekazuj nam swoje opinie na Twitterze lub w komentarzach poniżej oraz zgłaszaj błędy na stronie crbug.com/new.