Глава 08. Уловки мастеров Htmx
Расширенный Htmx
В этой главе мы собираемся более подробно изучить набор инструментов htmx. Мы уже многого добились благодаря тому, что узнали на данный момент. Тем не менее, когда вы разрабатываете приложения, управляемые гипермедиа, могут возникнуть моменты, когда вам потребуется использовать дополнительные параметры и методы.
Мы рассмотрим более сложные атрибуты в htmx, а также подробно остановимся на атрибутах, которые мы уже использовали.
Кроме того, мы рассмотрим функциональность, которую htmx предлагает помимо простых атрибутов HTML: как htmx расширяет стандартные HTTP-запросы и ответы, как htmx работает с событиями (и создает их), и как подходить к ситуациям, когда нет простой единой цели для страница, которую необходимо обновить.
Наконец, мы рассмотрим практические аспекты разработки htmx: как эффективно отлаживать приложения на основе htmx, соображения безопасности, которые необходимо учитывать при работе с htmx, и как настроить поведение htmx.
Благодаря функциям и методам, описанным в этой главе, вы сможете создавать чрезвычайно сложные пользовательские интерфейсы, используя только Htmx и, возможно, немного клиентских сценариев, дружественных к гипермедиа.
Htmx-атрибуты
На данный момент в нашем приложении мы использовали около пятнадцати различных атрибутов htmx. Наиболее важными из них были:
hx-get
, hx-post
и т. д.
Чтобы указать запрос AJAX, элемент должен сделать
hx-trigger
Чтобы указать событие, которое запускает запрос
hx-swap
Чтобы указать, как заменить возвращенное содержимое HTML в DOM.
hx-target
Чтобы указать, где в DOM заменить возвращаемое содержимое HTML.
Два из этих атрибутов hx-swap
и hx-trigger
поддерживают ряд полезных опций для создания более продвинутых приложений, управляемых гипермедиа.
hx-своп
Начнем с атрибута hx-swap. Это часто не включается в элементы, которые отправляют запросы на основе htmx, поскольку его поведение по умолчанию — , innerHTML
которое заменяет внутренний HTML-код элемента — имеет тенденцию охватывать большинство случаев использования.
Ранее мы видели ситуации, когда нам хотелось переопределить поведение по умолчанию и использовать outerHTML
, например, . А в главе 2 мы обсуждали некоторые другие варианты обмена, помимо этих двух: beforebegin
, afterend
и т. д.
В главе 5 мы также рассмотрели swap
модификатор задержки для hx-swap
, который позволил нам постепенно затухать некоторый контент перед его удалением из DOM.
В дополнение к этому hx-swap
предлагает дополнительный контроль со следующими модификаторами:
settle
Как и swap
, это позволяет вам применять определенную задержку между моментом замены контента в DOM и моментом «установления» его атрибутов, то есть обновления их старых значений (если таковые имеются) до новых значений. Это может дать вам детальный контроль над переходами CSS.
show
Позволяет указать элемент, который должен отображаться — то есть при необходимости прокручиваться в область просмотра браузера — после завершения запроса.
scroll
Позволяет указать прокручиваемый элемент (то есть элемент с полосами прокрутки), который должен быть прокручен вверх или вниз после завершения запроса.
focus-scroll
Позволяет указать, что htmx должен прокручиваться до элемента, находящегося в фокусе, после завершения запроса. По умолчанию для этого модификатора установлено значение «false».
Так, например, если бы у нас была кнопка, выдающая запрос GET
, и мы хотели бы прокрутить элемент до верхней части body
после завершения запроса, мы бы написали следующий HTML:
Это указывает htmx отображать верхнюю часть тела после того, как произойдет замена.
hx-триггер
Например hx-swap
, , hx-trigger
часто можно опустить при использовании htmx, поскольку поведение по умолчанию обычно соответствует вашему желанию. Напомним, что триггерные события по умолчанию определяются типом элемента:
Запросы на элементы
input
,textarea
&select
запускаются событиемchange
.Запросы к
form
элементам запускаются поsubmit
событию.Запросы ко всем остальным элементам инициируются событием
click
.
Однако бывают случаи, когда вам нужна более подробная спецификация триггера. Классическим примером является пример активного поиска, который мы реализовали в Contact.app:
Подробная спецификация триггера.
В этом примере использованы два модификатора, доступные для hx-trigger
атрибута:
delay
Позволяет указать задержку ожидания перед отправкой запроса. Если событие происходит снова, первое событие отбрасывается и таймер сбрасывается. Это позволяет «отклонять» запросы.
changed
Позволяет указать, что запрос должен быть выдан только при value
изменении свойства данного элемента.
hx-trigger
имеет несколько дополнительных модификаторов. Это имеет смысл, поскольку события довольно сложны, и мы хотим иметь возможность воспользоваться всей мощью, которую они предлагают. Подробнее о событиях мы поговорим ниже.
Вот другие модификаторы, доступные на hx-trigger
:
once
Данное событие вызовет запрос только один раз.
throttle
Позволяет регулировать события, выдавая их только один раз в определенный интервал. Это отличается от delay
того, что первое событие сработает немедленно, но любые последующие события не сработают, пока не истечет период времени регулирования.
from
Селектор CSS, который позволяет вам выбрать другой элемент для прослушивания событий. Мы увидим пример этого использования позже в этой главе.
target
Селектор CSS, который позволяет фильтровать события, выбирая только те, которые происходят непосредственно с данным элементом. В DOM события «переходят» к своим родительским элементам, поэтому click
событие на кнопке также вызывает click
событие на родительском элементе div
, вплоть до самого body
элемента. Иногда вам нужно указать событие непосредственно для данного элемента, и этот атрибут позволяет вам это сделать.
consume
Если для этой опции установлено значение true
, событие-триггер будет отменено и не распространится на родительские элементы.
queue
Эта опция позволяет вам указать, как события помещаются в очередь в htmx. По умолчанию, когда htmx получает триггерное событие, он выдает запрос и запускает очередь событий. Если запрос все еще находится в работе, когда получено другое событие, оно будет помещено в очередь и, когда запрос завершится, инициирует новый запрос. По умолчанию он сохраняет только последнее полученное событие, но вы можете изменить это поведение, используя этот параметр: например, вы можете установить его none
и игнорировать все триггерные события, которые происходят во время запроса.
Триггерные фильтры
Атрибут hx-trigger
также позволяет указать фильтр для событий, используя квадратные скобки, заключающие выражение JavaScript после имени события.
Допустим, у вас сложная ситуация, когда контакты можно восстановить только в определенных ситуациях. У вас есть функция JavaScript, contactRetrievalEnabled()
которая возвращает логическое значение, true
если контакты можно получить, и false
в противном случае. Как вы могли бы использовать эту функцию, чтобы разместить шлюз на кнопке, которая отправляет запрос /contacts
?
Чтобы сделать это с помощью фильтра событий в htmx, вы должны написать следующий HTML:
Запрос выдается по клику только при
contactRetrievalEnabled()
возвратеtrue
.
Кнопка не выдает запрос, если contactRetrievalEnabled()
возвращает false, что позволяет вам динамически контролировать время выполнения запроса. Существуют распространенные ситуации, требующие триггера событий, когда вы хотите отправить запрос только при определенных обстоятельствах:
если определенный элемент имеет фокус
если данная форма действительна
если набор входных данных имеет определенные значения
Используя фильтры событий, вы можете использовать любую логику для фильтрации запросов по htmx.
Синтетические события
В дополнение к этим модификаторам hx-trigger
предлагает несколько «синтетических» событий, то есть событий, которые не являются частью обычного DOM API. Мы уже видели load
это revealed
в наших примерах отложенной загрузки и бесконечной прокрутки, но htmx также предоставляет intersect
событие, которое срабатывает, когда элемент пересекает свой родительский элемент.
Пересечение дает вам детальный контроль над тем, когда именно должен быть запущен запрос. Например, вы можете установить пороговое значение и указать, что запрос будет выдаваться только тогда, когда элемент виден на 50 %.
Другие атрибуты
Htmx предлагает множество других, менее часто используемых атрибутов для тонкой настройки поведения вашего приложения, управляемого гипермедиа.
Вот некоторые из наиболее полезных:
hx-push-url
«Проталкивает» URL-адрес запроса (или какое-либо другое значение) в панель навигации.
hx-заповедник
Сохраняет часть DOM между запросами; исходное содержимое будет сохранено независимо от того, что будет возвращено.
hx-синхронизация
Синхронизированные запросы между двумя или более элементами.
hx-отключить
Отключает поведение htmx для этого элемента и всех дочерних элементов. Мы вернемся к этому, когда будем обсуждать тему безопасности.
Давайте посмотрим на hx-sync
, который позволяет нам синхронизировать запросы AJAX между двумя или более элементами. Рассмотрим простой случай, когда у нас есть две кнопки, которые нацелены на один и тот же элемент на экране:
Это нормально и будет работать, но что, если пользователь нажмет кнопку «Получить контакты», а затем на ответ на запрос потребуется некоторое время? И тем временем пользователь нажимает кнопку «Получить настройки»? В этом случае у нас будет одновременно выполняться два запроса.
Если /settings
запрос завершился первым и отобразил информацию о настройках пользователя, они могут быть очень удивлены, если начнут вносить изменения, а затем внезапно запрос /contacts
завершится и вместо этого все тело будет заменено контактами!
Чтобы справиться с этой ситуацией, мы могли бы рассмотреть возможность использования , hx-indicator
чтобы предупредить пользователя о том, что что-то происходит, что снизит вероятность того, что он нажмет вторую кнопку. Но если мы действительно хотим гарантировать, что между этими двумя кнопками одновременно выполняется только один запрос, правильно будет использовать атрибут hx-sync
. Давайте заключим обе кнопки в div
и устраним избыточную hx-target
спецификацию, подняв атрибут до этого значения div
. Затем мы можем использовать hx-sync
этот div для координации запросов между двумя кнопками.
Вот наш обновленный код:
.Синхронизация двух кнопок
Поднимите повторяющиеся
hx-target
атрибуты родительскому элементуdiv
.Синхронизируйте с родительским файлом
div
.
Размещая hx-sync
атрибут со div
значением this
, мы говорим: «Синхронизируйте все запросы htmx, которые происходят внутри этого div
элемента, друг с другом». Это означает, что если у одной кнопки уже есть выполняющийся запрос, другие кнопки внутри div
не будут выдавать запросы до тех пор, пока он не завершится.
События
До сих пор мы работали с событиями JavaScript в htmx в основном через hx-trigger
атрибут. Этот атрибут оказался мощным механизмом управления нашим приложением с использованием декларативного, дружественного к HTML синтаксиса.
Однако с событиями мы можем сделать гораздо больше. События играют решающую роль как в расширении HTML как гипермедиа, так и, как мы увидим, в сценариях, дружественных к гипермедиа. События — это «клей», который объединяет DOM, HTML, htmx и сценарии. Вы можете думать о DOM как о сложной «шине событий» для приложений.
События, генерируемые Htmx
Помимо упрощения реакции на события, htmx также генерирует множество полезных событий. Вы можете использовать эти события, чтобы добавить больше функциональности вашему приложению либо через HTML-код, либо с помощью сценариев.
Вот некоторые из наиболее часто используемых событий, запускаемых htmx:
htmx:load
Срабатывает, когда новый контент загружается в DOM с помощью htmx.
htmx:configRequest
Срабатывает перед выдачей запроса, что позволяет программно настроить запрос или полностью отменить его.
htmx:afterRequest
Запускается после ответа на запрос.
htmx:abort
Пользовательское событие, которое можно отправить элементу на базе htmx, чтобы прервать открытый запрос.
Использование события htmx:configRequest
Давайте рассмотрим пример того, как работать с событиями, создаваемыми htmx. Мы будем использовать это htmx:configRequest
событие для настройки HTTP-запроса.
Рассмотрим следующий сценарий: ваша серверная команда решила, что они хотят, чтобы вы включали сгенерированный сервером токен для дополнительной безопасности в каждый запрос. Токен будет храниться в localStorage
браузере, в слоте special-token
.
Токен устанавливается с помощью JavaScript (пока не беспокойтесь о деталях), когда пользователь впервые входит в систему:
Получите значение токена, а затем установите его в localStorage.
Серверная команда хочет, чтобы вы включали этот специальный токен в каждый запрос, сделанный htmx, в качестве заголовка X-SPECIAL-TOKEN
. Как вы могли этого добиться? Один из способов — перехватить htmx:configRequest
событие и обновить detail.headers
объект этим токеном из localStorage
.
В VanillaJS это будет выглядеть примерно так, если разместить его в <script>
теге <head>
нашего HTML-документа:
Получите значение из локального хранилища и поместите его в заголовок.
Как видите, мы добавляем новое значение в headers
свойство подробностей события. После выполнения обработчика событий это headers
свойство считывается htmx и используется для создания заголовков запроса AJAX, который он делает.
Свойство detail
события htmx:configRequest
содержит множество полезных свойств, которые вы можете обновить, чтобы изменить «форму» запроса, в том числе:
detail.parameters
Позволяет добавлять или удалять параметры запроса
detail.target
Позволяет обновить цель запроса
detail.verb
Позволяет обновлять HTTP-глагол запроса (например GET
)
Так, например, если команда серверной стороны решила, что токен должен быть включен в качестве параметра, а не в качестве заголовка запроса, вы можете обновить свой код, чтобы он выглядел так:
Получите значение из локального хранилища и установите его в параметр.
Как видите, это дает вам большую гибкость при обновлении запроса AJAX, который делает htmx.
Отмена запроса с помощью htmx:abort
Мы можем прослушивать любое из множества полезных событий из htmx и реагировать на эти события, используя hx-trigger
. Что еще мы можем делать с событиями?
Оказывается, сам htmx прослушивает одно специальное событие: htmx:abort
. Когда htmx получает это событие для элемента, к которому находится запрос, он прерывает запрос.
Рассмотрим ситуацию, когда у нас есть потенциально длительный запрос к /contacts
, и мы хотим предложить пользователям возможность отменить запрос. Нам нужна кнопка, которая отправляет запрос, конечно же, управляемая htmx, а затем еще одна кнопка, которая будет отправлять событие htmx:abort
первой.
Вот как может выглядеть код:
Обычный HTML-
GET
запрос к/contacts
JavaScript для поиска кнопки и отправки ей
htxm:abort
события
Итак, теперь, если пользователь нажимает кнопку «Получить контакты» и запрос занимает некоторое время, он может нажать кнопку «Отменить» и завершить запрос. Конечно, в более сложном пользовательском интерфейсе вы можете захотеть отключить кнопку «Отмена», если только не выполняется HTTP-запрос, но это было бы сложно реализовать на чистом JavaScript.
К счастью, это не так уж плохо реализовать в гиперскрипте, поэтому давайте посмотрим, как это будет выглядеть:
Теперь у нас есть кнопка «Отмена», которая отключается только тогда, когда запрос от contacts-btn
кнопки находится в полете. И чтобы это произошло, мы используем преимущества событий, генерируемых и обрабатываемых с помощью htmx, а также дружественного к событиям синтаксиса гиперскрипта. Ловко!
События, генерируемые сервером
В следующем разделе мы поговорим подробнее о различных способах, с помощью которых htmx улучшает регулярные HTTP-запросы и ответы, но, поскольку это связано с событиями, мы собираемся обсудить один заголовок HTTP-ответа, который поддерживает htmx: HX-Trigger
. Ранее мы обсуждали, как HTTP-запросы и ответы поддерживают заголовки — пары имя-значение, содержащие метаданные о данном запросе или ответе. Мы воспользовались HX-Trigger
заголовком запроса, который включает идентификатор элемента, вызвавшего данный запрос.
В дополнение к этому заголовку запроса , htmx также поддерживает заголовок ответа, также называемый HX-Trigger
. Этот заголовок ответа позволяет инициировать событие для элемента, отправившего запрос AJAX. Это оказывается мощным способом несвязанной координации элементов в DOM.
Чтобы увидеть, как это может работать, давайте рассмотрим следующую ситуацию: у нас есть кнопка, которая получает новые контакты из некоторой удаленной системы на сервере. Мы проигнорируем детали реализации на стороне сервера, но мы знаем, что если мы введем POST
путь /sync
, это вызовет синхронизацию с системой.
Теперь эта синхронизация может привести, а может и не привести к созданию новых контактов. В случае создания новых контактов мы хотим обновить нашу таблицу контактов. В случае, если контакты не созданы, мы не хотим обновлять таблицу.
Чтобы реализовать это, мы могли бы условно добавить HX-Trigger
заголовок ответа со значением contacts-updated
:
Обращение к удаленной системе, которая синхронизировала с ней нашу базу контактов
Если какие-либо контакты были обновлены, мы условно запускаем
contacts-updated
событие на клиенте.
Это значение вызовет contacts-updated
событие на кнопке, которая отправила запрос AJAX к /sync
. Затем мы можем воспользоваться модификатором from:
атрибута hx-trigger
для прослушивания этого события. С помощью этого шаблона мы можем эффективно запускать запросы htmx со стороны сервера.
Вот как может выглядеть код на стороне клиента:
Ответ на этот запрос может условно вызвать
contacts-updated
событие.Эта таблица прослушивает событие и обновляется, когда оно происходит.
Таблица прослушивает событие contacts-updated
и делает это для body
элемента. Он прослушивает элемент, body
поскольку событие всплывает из кнопки, и это позволяет нам не связывать кнопку и таблицу вместе: мы можем перемещать кнопку и таблицу по своему усмотрению, и с помощью событий будет продолжаться желаемое поведение. работать нормально. Кроме того, мы можем захотеть, чтобы другие элементы или запросы инициировали contacts-updated
событие, поэтому это обеспечивает общий механизм обновления таблицы контактов в нашем приложении.
HTTP-запросы и ответы
Мы только что увидели расширенную функцию HTTP-ответов, поддерживаемую htmx, HX-Trigger
заголовок ответа, но htmx поддерживает еще несколько заголовков как для запросов, так и для ответов. В главе 4 мы обсуждали заголовки, присутствующие в HTTP-запросах. Вот некоторые из наиболее важных заголовков, которые вы можете использовать для изменения поведения htmx с ответами HTTP:
HX-Location
Вызывает перенаправление на стороне клиента в новое место.
HX-Push-Url
Помещает новый URL-адрес в адресную строку
HX-Refresh
Обновляет текущую страницу
HX-Retarget
Позволяет указать новую цель для замены содержимого ответа на стороне клиента.
Коды ответа HTTP
Еще более важным, чем заголовки ответа, с точки зрения информации, передаваемой клиенту, является код ответа HTTP . Мы обсуждали коды ответов HTTP в главе 3. В целом htmx обрабатывает различные коды ответов так, как и следовало ожидать: он меняет содержимое для всех кодов ответа 200-го уровня и ничего не делает для других. Однако есть два «специальных» 200-уровневых кода ответа:
204 No Content
- Когда htmx получает этот код ответа, он не будет заменять какой-либо контент в DOM (даже если ответ имеет тело).286
- Когда htmx получит этот код ответа на опрос, он остановит опрос.
Вы можете переопределить поведение htmx в отношении кодов ответа, как вы уже догадались, отвечая на событие! Событие htmx:beforeSwap
позволяет вам изменить поведение htmx по отношению к различным кодам состояния.
Предположим, что вместо того, чтобы ничего не делать при 404
возникновении ошибки, вы хотите предупредить пользователя о том, что произошла ошибка. Для этого вам нужно вызвать метод JavaScript showNotFoundError()
. Давайте добавим немного кода, чтобы использовать htmx:beforeSwap
это событие:
Подключитесь к
htmx:beforeSwap
событию.Если код ответа —
404
, покажите пользователю диалоговое окно.
Обновление другого контента
Выше мы увидели, как использовать событие, инициируемое сервером, через HX-Trigger
заголовок ответа HTTP, чтобы обновить часть DOM на основе ответа на другую часть DOM. Этот метод решает общую проблему, возникающую в приложениях, управляемых гипермедиа: «Как мне обновить другой контент?» Ведь в обычных HTTP-запросах есть только одна «цель» — весь экран, и, аналогично, в запросах на основе htmx есть только одна цель: либо явная, либо неявная цель элемента.
Если вы хотите обновить другой контент в формате Htmx, у вас есть несколько вариантов:
Расширение вашего выбора
Первый и самый простой вариант — «расширить цель». То есть вместо того, чтобы просто заменять небольшую часть экрана, расширьте цель вашего htmx-запроса, пока она не станет достаточно большой, чтобы вместить все элементы, которые необходимо обновить на экране. Это имеет огромное преимущество: простота и надежность. Обратной стороной является то, что он может не обеспечить желаемый пользовательский интерфейс и может не подходить для определенного макета шаблона на стороне сервера. В любом случае, мы всегда рекомендуем сначала подумать хотя бы об этом подходе.
Внеполосные свопы
Второй вариант, немного более сложный, — воспользоваться поддержкой внеполосного контента в htmx. Когда htmx получает ответ, он проверяет его на наличие содержимого верхнего уровня, включающего этот hx-swap-oob
атрибут. Этот контент будет удален из ответа, поэтому он не будет заменен в DOM обычным способом. Вместо этого он будет заменен на контент, которому он соответствует по идентификатору.
Давайте посмотрим на пример. Рассмотрим ситуацию, которая у нас была ранее, когда таблицу контактов необходимо обновить, если интеграция удаляет какие-либо новые контакты. Ранее мы решали эту проблему, используя события и событие, инициируемое сервером, через HX-Trigger
заголовок ответа.
На этот раз мы будем использовать hx-swap-oob
атрибут в ответе на POST
to /integrations/1
. Новое содержимое таблицы контактов будет добавлено к ответу.
Кнопка по-прежнему выдает
POST
сообщение/integrations/1
.Таблица больше не ожидает событий, но теперь у нее есть идентификатор.
Далее ответ на POST
to /integrations/1
будет включать в себя содержимое, которое необходимо заменить на кнопку, в соответствии с обычным механизмом htmx. Но он также будет включать новую, обновленную версию таблицы контактов, которая будет помечена как hx-swap-oob="true"
. Этот контент будет удален из ответа и не будет вставлен в кнопку. Вместо этого она заменяется в DOM вместо существующей таблицы, поскольку имеет соответствующий идентификатор.
Этот контент будет помещен в кнопку.
Этот контент будет удален из ответа и заменен по идентификатору.
В зависимости от того, как именно работает ваша технология шаблонов на стороне сервера и какой уровень интерактивности требуется вашему приложению, внеполосная замена может стать мощным механизмом обновления контента.
События
Наконец, самый сложный механизм обновления контента — это тот, который мы видели в разделе «События»: использование событий, инициируемых сервером, для обновления элементов. Этот подход может быть очень чистым, но также требует более глубоких концептуальных знаний HTML и событий, а также приверженности подходу, управляемому событиями. Хотя нам нравится такой стиль разработки, он подходит не всем. Обычно мы рекомендуем этот шаблон только в том случае, если философия htmx-гипермедиа, управляемой событиями, действительно вам подходит.
Однако, если это действительно говорит с вами, мы говорим: действуйте. Используя этот подход, мы создали несколько очень сложных и гибких пользовательских интерфейсов, и он нам очень нравится.
Быть прагматичным
Все эти подходы к проблеме «Обновление другого контента» будут работать, и часто будут работать хорошо. Однако может наступить момент, когда будет проще использовать другой подход для вашего пользовательского интерфейса, например реактивный. Как бы нам ни нравился подход гипермедиа, реальность такова, что существуют некоторые шаблоны UX, которые просто невозможно легко реализовать с его помощью. Каноническим примером такого рода шаблона, о котором мы упоминали ранее, является что-то вроде живой онлайн-таблицы: это просто слишком сложный пользовательский интерфейс со слишком большим количеством взаимозависимостей, чтобы его можно было эффективно реализовать посредством обмена гипермедиа с сервером.
В подобных случаях и каждый раз, когда вы чувствуете, что решение на основе htmx оказывается более сложным, чем другой подход, мы рекомендуем вам рассмотреть другую технологию. Будьте прагматичны и используйте правильный инструмент для работы. Вы всегда можете использовать htmx для тех частей вашего приложения, которые не так сложны и не требуют всей сложности реактивной среды, и сэкономить этот бюджет сложности для тех частей, которые требуют этого.
Мы рекомендуем вам изучить множество различных веб-технологий, обращая внимание на сильные и слабые стороны каждой из них. Это даст вам глубокий арсенал инструментов, к которому можно будет обратиться в случае возникновения проблем. Наш опыт показывает, что благодаря htmx гипермедиа становится инструментом, к которому вы можете часто обращаться.
Отладка
Нам не стыдно признаться: мы большие поклонники мероприятий. Они лежат в основе практически любого интересного пользовательского интерфейса и особенно полезны в DOM, когда они доступны для общего использования в HTML. Они позволяют создавать хорошо изолированное программное обеспечение, часто сохраняя при этом локальность поведения, которая нам так нравится.
Однако события не идеальны. Одна из областей, где с событиями может быть особенно сложно справиться, — это отладка : часто требуется знать, почему событие не происходит. Но где можно установить точку останова для того, чего не происходит? Ответ на данный момент таков: вы не можете.
Есть два метода, которые могут помочь в этом отношении: один предоставляется htmx, другой — Chrome, браузером Google.
Регистрация событий Htmx
Первый метод, предоставляемый самим htmx, — это вызов htmx.logAll()
метода. Когда вы это сделаете, htmx будет регистрировать все внутренние события, которые происходят в ходе его работы, загрузки контента, реагирования на события и т. д.
Не совсем приятно для глаз, не так ли?
Но если вы глубоко вздохнете и прищуритесь, то увидите, что все не так уж и плохо: серия htmx-событий, некоторые из которых мы уже видели раньше (есть htmx:configRequest
!), записываются в консоль вместе с элементом они срабатывают.
После небольшого чтения и фильтрации вы сможете разобраться в потоке событий, и это может помочь вам отладить проблемы, связанные с htmx.
Мониторинг событий в Chrome
Предыдущий метод полезен, если проблема возникает где-то внутри htmx, но что, если htmx вообще не запускается? Такое случается иногда, например, когда вы случайно где-то неправильно ввели название события.
В подобных случаях вам понадобится воспользоваться инструментом, доступным в самом браузере. К счастью, браузер Chrome от Google предоставляет очень полезную функцию, monitorEvents()
которая позволяет отслеживать все события, происходящие на элементе.
Эта функция доступна только в консоли, поэтому вы не можете использовать ее в коде на своей странице. Но если вы работаете с htmx в Chrome и вам интересно, почему событие не запускается для элемента, вы можете открыть консоль разработчика и ввести следующее:
Затем это выведет на консоль все события, которые запускаются на элементе с идентификатором . some-element
Это может быть очень полезно для понимания того, на какие именно события вы хотите реагировать с помощью htmx, или для устранения неполадок, почему ожидаемое событие не происходит.
Использование этих двух методов поможет вам (мы надеемся, что нечасто) устранять проблемы, связанные с событиями, при разработке с использованием htmx.
Вопросы безопасности
В целом, htmx и гипермедиа, как правило, более безопасны, чем тяжелые подходы JavaScript к созданию веб-приложений. Это связано с тем, что, перенося большую часть обработки на серверную часть, подход с использованием гипермедиа имеет тенденцию не предоставлять конечным пользователям большую часть поверхности вашей системы для манипуляций и махинаций.
Однако даже при использовании гипермедиа существуют ситуации, требующие осторожности при разработке. Особую озабоченность вызывают ситуации, когда пользовательский контент показывается другим пользователям: умный пользователь может попытаться вставить код htmx, который обманным путем заставит других пользователей щелкнуть контент, который инициирует действия, которые они не хотят предпринимать.
В общем, весь пользовательский контент должен экранироваться на стороне сервера, и большинство серверных платформ рендеринга предоставляют функциональные возможности для обработки этой ситуации. Но всегда есть риск, что что-то ускользнет.
Чтобы помочь вам лучше спать по ночам, htmx предоставляет атрибут hx-disable
. Когда этот атрибут помещается в элемент, все атрибуты htmx внутри этого элемента будут игнорироваться.
Политики безопасности контента и Htmx
Распространенной функцией, которую можно отключить с помощью CSP, является eval()
функция JavaScript, которая позволяет оценивать произвольный код JavaScript из строки. Это оказалось проблемой безопасности, и многие команды решили, что не стоит рисковать, оставляя его включенным в своих веб-приложениях.
Htmx не использует интенсивно eval()
, поэтому CSP с этим ограничением подойдет. Единственная функция, на которую все-таки полагается, eval()
— это фильтры событий, описанные выше. Если вы решите отключить его eval()
для своего веб-приложения, вы не сможете использовать синтаксис фильтрации событий.
Настройка
Для htmx доступно большое количество вариантов конфигурации. Вот некоторые примеры того, что вы можете настроить:
Стиль подкачки по умолчанию
Задержка замены по умолчанию
Тайм-аут запросов AJAX по умолчанию
Htmx обычно настраивается с помощью meta
тега, расположенного в заголовке страницы. Имя метатега должно быть htmx-config
, а атрибут содержимого должен содержать переопределения конфигурации в формате JSON. Вот пример:
В этом случае мы переопределяем стиль подкачки по умолчанию с обычного innerHTML
на outerHTML
. Это может быть полезно, если вы используете его outerHTML
чаще innerHTML
и хотите избежать необходимости явно устанавливать это значение подкачки во всем приложении.
Примечания к HTML: семантический HTML
Сказание людям «использовать семантический HTML» вместо «читать спецификацию» привело к тому, что многие люди догадывались о значении тегов: «Мне это кажется довольно семантическим!» — вместо того, чтобы заниматься спец.
Я думаю, что когда меня просят написать осмысленный HTML, это лучше освещает путь к пониманию того, что речь идет не о том, что текст значит для людей, а об использовании тегов для целей, указанных в спецификациях, для удовлетворения потребностей программного обеспечения, такого как браузеры, вспомогательные технологии. и поисковые системы.
— https://t-ravis.com/post/doc/semantic_the_8_letter_s-word/
Мы рекомендуем говорить и писать о совместимом HTML. (Мы всегда можем покататься на велосипеде дальше). Используйте элементы в полной мере, предусмотренные спецификацией HTML, и позвольте программному обеспечению извлечь из них любое значение, которое они могут.
Last updated