bythe.net
← К ленте
Новинки

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 в приложении никуда не исчезает, но теперь у него есть правильное место.

Войти, чтобы оценить материал

Комментарии

Войти, чтобы оставить комментарий