Руководство по морфингу
Как работают подмены с морфингом, когда их использовать и как ими управлять.
Морфинг DOM
Морфинг DOM — это метод, при котором существующие элементы DOM «морфируются», чтобы соответствовать новому содержимому. Алгоритм морфинга проходит по старому DOM и изменяет его, придавая ему форму нового. Благодаря этому неизменившиеся узлы обычно сохраняют свою идентичность.
С точки зрения пользователя это может быть очень удобно: фокус, выделение текста, положение прокрутки и воспроизведение видео могут сохраняться без перерыва при добавлении нового содержимого в DOM. Для разработчиков это позволяет сохранять любое состояние, которое скрипт или веб-компонент задали элементу.
Авторы htmx создали алгоритм морфинга под названием idiomorph. Вместе с ним было выпущено расширение, рекомендованное в htmx 2 для тех, кто хотел использовать подмену с морфингом. Были доступны и другие алгоритмы морфинга: Morphdom и Morph от Alpine
В htmx 4 алгоритм idiomorph встроен в htmx, поэтому можно задавать стратегии подмены innerMorph и outerMorph без подключения каких-либо расширений.
Использование подмен с морфингом
Чтобы использовать морфинг в htmx 4, достаточно указать его с помощью hx-swap:
<div id="status" hx-get="/status" hx-trigger="every 5s" hx-swap="innerMorph"> <h2>Build: passing</h2> <input name="note" placeholder="Add a note"> </div>
В этом случае любые изменения содержимого div будут внесены с помощью морфинга, не отвлекая пользователя, если поле ввода находится в фокусе.
В htmx подмены без морфинга тоже довольно хорошо сохраняют такие параметры, как фокус поля ввода. Кроме того, есть такие средства, как hx-preserve, которые позволяют гарантировать, что определённый элемент сохранится при подменах. Поэтому морфинг нужен не всегда, но во многих случаях он может быть полезен.
Стили подмены
Два стиля морфинга для hx-swap:
| Стиль | Описание |
|---|---|
innerMorph |
Морфирует дочерние элементы целевого элемента. Сам целевой элемент не изменяется. |
outerMorph |
Морфирует целевой элемент вместе с его дочерними элементами. |
<div id="content" hx-get="/refresh" hx-swap="innerMorph"> ... </div>
Они аналогичны подменам innerHTML и outerHTML.
Алгоритм Idiomorph
Алгоритм Idiomorph работает примерно следующим образом:
- Он строит карту всех
id, которые встречаются и в старом, и в новом содержимом - Затем он формирует набор всех
id, найденных внутри узлов (то есть среди дочерних элементов) - После этого он пытается изменить старое содержимое, придав ему форму нового, с минимально возможным количеством перемещений
На практике рекомендуется задавать атрибуты id элементам, которые должны оставаться неизменными. Элемент с таким же id сохранится в новом DOM. Элементы без id, но содержащие элементы со стабильными атрибутами id, как правило, тоже останутся неизменными.
Благодаря Idiomorph не нужно чрезмерно увлекаться атрибутами id, но для стабильного поведения при морфинге важным элементам всё же следует задавать атрибуты id.
Исключение элементов
Иногда при морфинге нужно пропустить некоторые элементы. Для этого предусмотрены два атрибута:
-
hx-morph-skip— заморозить элемент. Атрибуты и дочерние элементы останутся без изменений. -
hx-morph-skip-children— морфировать атрибуты, оставив дочерние элементы без изменений.
<custom-widget hx-morph-skip>...</custom-widget> <div hx-morph-skip-children class="chart">...</div>
Также можно расширить глобальные селекторы:
htmx.config.morphSkip = '[hx-morph-skip], custom-widget, .frozen'; htmx.config.morphSkipChildren = '[hx-morph-skip-children], lit-component, .sortable';
Это позволяет отключить морфинг для сторонних виджетов, веб-компонентов и т. п.
Значения полей ввода и фокус
Морфинг может быть очень полезен для замены или обновления форм при динамической проверке данных.
Подмены с морфингом автоматически сохраняют значение поля ввода или текстовой области, находящихся в фокусе, даже если сервер возвращает другое значение. Это не позволяет устаревшим ответам перезаписать ввод пользователя.
Для полей ввода, не находящихся в фокусе, htmx сохраняет введённое пользователем значение, если атрибут value не изменился в старом и новом содержимом. Это отличается от поведения idiomorph по умолчанию: при каждом морфинге он сбрасывает свойство .value в соответствии со значением атрибута value. Чтобы сохранять значения всех полей ввода, пусть сервер возвращает поля без изменения атрибута value либо добавьте 'value' к htmx.config.morphIgnore.
Настройка
При настройке поведения морфинга доступны ещё два параметра конфигурации:
-
htmx.config.morphIgnore— список префиксов имён атрибутов, которые htmx никогда не изменяет. По умолчанию —["data-htmx-powered"]. -
htmx.config.morphScanLimit, значение по умолчанию —10. Определяет, насколько далеко htmx просматривает соседние элементы в поисках позиционного совпадения (не по id), прежде чем прекратить поиск. Чем меньше значение, тем выше скорость, но тем больше совпадений будет пропущено.
См. также
Licensed under the Zero-Clause BSD License.
https://four.htmx.org/docs/morphing-swaps-guide/