Phoenix LiveView: хуки теперь живут рядом с шаблоном
Colocated hooks позволяют писать JavaScript прямо в HEEx-шаблоне, а сборщик сам собирает его в бандл. Меньше прыжков между файлами и меньше забытого кода в app.js.
Проблема, которую решают
LiveView держит состояние на сервере и отправляет в браузер только диффы разметки. Для большинства экранов этого достаточно, но иногда нужен настоящий JavaScript: маска ввода, интеграция с библиотекой графиков, фокус на поле после открытия модального окна.
Раньше это делалось так: в шаблоне ставился phx-hook="PhoneNumber", а сам объект хука писался в assets/js/app.js и передавался в LiveSocket. Работало, но со временем app.js превращался в свалку хуков, половина которых относилась к давно удалённым шаблонам.
Как теперь
Хук объявляется прямо в шаблоне, рядом с элементом, который его использует:
<input type="text" id="phone" phx-hook=".PhoneNumber" />
<script :type={Phoenix.LiveView.ColocatedHook} name=".PhoneNumber">
export default {
mounted() {
this.el.addEventListener("input", e => {
const digits = this.el.value.replace(/\D/g, "")
const m = digits.match(/^(\d{3})(\d{3})(\d{4})$/)
if (m) this.el.value = `${m[1]}-${m[2]}-${m[3]}`
})
}
}
</script>
Имя начинается с точки — это признак colocated-хука. При компиляции LiveView извлекает содержимое <script> в отдельный файл внутри _build, а app.js подключает их все одной строкой импорта. В браузер уходит обычный бандл, никакого inline-кода на странице.
Что это даёт
- Локальность. Шаблон и его JavaScript в одном файле. Удалил компонент — удалился и хук.
- Область видимости. Хук с точкой в имени привязан к модулю, где объявлен. Два компонента могут иметь
.Chartс разной реализацией, и они не столкнутся. - Компоненты из библиотек. Пакет с HEEx-компонентами может нести свой JS, не заставляя пользователя редактировать
app.js. - Тот же механизм для CSS. Через
Phoenix.LiveView.ColocatedJSможно так же извлекать любой JS-модуль, а colocated CSS дополняет картину.
Что не меняется
Внешние хуки в app.js продолжают работать. Для больших кусков клиентского кода, которые переиспользуются по всему приложению, они по-прежнему уместны. Colocated-вариант — для кода, который принадлежит конкретному шаблону.
Правило про phx-update="ignore" тоже никуда не делось: если хук сам управляет DOM внутри элемента, LiveView нужно попросить не трогать этот элемент при обновлениях.
Как включить
Нужны LiveView 1.1 или новее и esbuild из стандартной настройки Phoenix. Генераторы свежих версий уже добавляют импорт colocated-хуков в app.js; в старом проекте достаточно одной строки:
import {hooks as colocatedHooks} from "phoenix-colocated/my_app"
и передать colocatedHooks в LiveSocket вместе с остальными.
Итог
Небольшое изменение, которое убирает одну из главных причин раздражения при работе с LiveView. JavaScript в приложении никуда не исчезает, но теперь у него есть правильное место.
Войти, чтобы оценить материал
Комментарии
Войти, чтобы оставить комментарий