Spec-Zone.ru › Phoenix

Добро пожаловать

Исходный код

Добро пожаловать в документацию Phoenix LiveView. Phoenix LiveView позволяет создавать насыщенные пользовательские интерфейсы в реальном времени с помощью HTML, отрисовываемого на сервере. Общий обзор LiveView и его преимуществ доступен в нашем README.

Что такое LiveView?

LiveView — это процессы, которые получают события, обновляют своё состояние и отображают изменения на странице в виде разниц.

Модель программирования LiveView декларативна: вместо того чтобы говорить «когда произойдёт событие X, измените Y на странице», события в LiveView представляют собой обычные сообщения, которые могут вызывать изменения состояния. После изменения состояния LiveView повторно отрисовывает соответствующие части HTML-шаблона и отправляет их в браузер, который обновляет страницу наиболее эффективным способом.

Состояние LiveView — это не что иное, как функциональные неизменяемые структуры данных Elixir. События представляют собой либо внутренние сообщения приложения (обычно отправляемые через Phoenix.PubSub), либо сообщения, отправленные клиентом/браузером.

Каждый LiveView сначала статически отрисовывается в рамках обычного HTTP-запроса, что обеспечивает быстрое время до «первой значимой отрисовки» (First Meaningful Paint), а также помогает поисковым системам и системам индексирования. Затем между клиентом и сервером устанавливается постоянное соединение. Это позволяет приложениям LiveView быстрее реагировать на события пользователя, поскольку по сравнению с запросами без сохранения состояния, для которых при каждом запросе необходимо выполнять аутентификацию, декодирование, загрузку и кодирование данных, требуется меньше работы и передачи данных.

Пример

LiveView включён по умолчанию в приложениях Phoenix. Поэтому для использования LiveView необходимо предварительно установить Phoenix и создать первое приложение. Если вы ещё этого не сделали, ознакомьтесь с руководством по установке Phoenix, чтобы начать работу.

Поведение LiveView задаётся модулем, реализующим набор функций обратного вызова. Рассмотрим пример. Сохраните приведённый ниже файл в lib/my_app_web/live/thermostat_live.ex. Не забудьте заменить каталог my_app_web и модуль MyAppWeb на имя вашего приложения:

defmodule MyAppWeb.ThermostatLive do
  use MyAppWeb, :live_view

  def render(assigns) do
    ~H"""
    Current temperature: {@temperature}°F
    <button phx-click="inc_temperature">+</button>
    """
  end

  def mount(_params, _session, socket) do
    temperature = 70 # Let's assume a fixed temperature for now
    {:ok, assign(socket, :temperature, temperature)}
  end

  def handle_event("inc_temperature", _params, socket) do
    {:noreply, update(socket, :temperature, &(&1 + 1))}
  end
end

В приведённом выше модуле определены три функции (это обратные вызовы, необходимые для LiveView). Первая из них — render/1, которая получает сокет assigns и отвечает за возврат содержимого, отображаемого на странице. Для определения шаблона HEEx мы используем сигил ~H; это название означает HTML+EEx. HEEx расширяет встроенные шаблоны EEx в Elixir, добавляя проверку HTML, компоненты на основе синтаксиса, интеллектуальное отслеживание изменений и многое другое. Подробнее о синтаксисе шаблонов читайте в разделе Phoenix.Component.sigil_H/2 (обратите внимание: Phoenix.Component импортируется автоматически при использовании Phoenix.LiveView).

Данные для отрисовки поступают из обратного вызова mount. Обратный вызов mount вызывается при запуске LiveView. В нём можно получить доступ к параметрам запроса, прочитать данные, сохранённые в сессии (обычно это данные, позволяющие определить текущего пользователя), и получить сокет. В сокете хранится всё состояние, включая assigns. mount присваивает сокету значение температуры по умолчанию. Поскольку структуры данных Elixir неизменяемы, API LiveView часто получают сокет и возвращают обновлённый сокет. Затем мы возвращаем {:ok, socket}, чтобы сообщить об успешном монтировании LiveView. После mount LiveView отрисует страницу со значениями из assigns и отправит её клиенту.

Если посмотреть на отрисованный HTML, вы заметите кнопку с атрибутом phx-click. При нажатии на кнопку на сервер отправляется событие "inc_temperature", которое сопоставляется с обратным вызовом handle_event и обрабатывается им. Этот обратный вызов обновляет сокет и возвращает {:noreply, socket} с обновлённым сокетом. В LiveView (как и в Elixir в целом) обратные вызовы handle_* вызываются в ответ на определённое действие — в данном случае на нажатие кнопки пользователем. Возвращаемое значение {:noreply, socket} означает, что браузеру не отправляются дополнительные ответы, а лишь отображается новая версия страницы. Затем LiveView вычисляет разницы и отправляет их клиенту.

Теперь мы готовы отобразить LiveView. Можно напрямую предоставить LiveView через маршрутизатор:

defmodule MyAppWeb.Router do
  use MyAppWeb, :router

  pipeline :browser do
    ...
  end

  scope "/", MyAppWeb do
    pipe_through :browser
    ...

    live "/thermostat", ThermostatLive
  end
end

После отрисовки LiveView отправляется обычный ответ HTML. При создании приложения Phoenix с помощью mix phx.new установщик также создаёт файл ./assets/js/app.js со следующим кодом:

import {Socket} from "phoenix"
import {LiveSocket} from "phoenix_live_view"

let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
liveSocket.connect()

Поэтому клиент JavaScript подключится через WebSockets, а mount/3 будет вызван внутри запущенного процесса LiveView.

Параметры и сессия

Обратный вызов mount получает три аргумента: параметры запроса, сессию и сокет.

Параметры можно использовать для чтения данных из URL. Например, если предположить, что где-то определён модуль Thermostat, который может считывать эти данные по названию дома, можно написать следующее:

def mount(%{"house" => house}, _session, socket) do
  temperature = Thermostat.get_house_reading(house)
  {:ok, assign(socket, :temperature, temperature)}
end

А затем добавить в маршрутизатор:

live "/thermostat/:house", ThermostatLive

Сессия извлекает данные из подписанной (или зашифрованной) cookie. Здесь можно хранить данные для аутентификации, например current_user_id:

def mount(_params, %{"current_user_id" => user_id}, socket) do
  temperature = Thermostat.get_user_reading(user_id)
  {:ok, assign(socket, :temperature, temperature)}
end

Phoenix включает встроенные генераторы аутентификации. См. mix phx.gen.auth.

На практике чаще всего используются оба способа:

def mount(%{"house" => house}, %{"current_user_id" => user_id}, socket) do
  temperature = Thermostat.get_house_reading(user_id, house)
  {:ok, assign(socket, :temperature, temperature)}
end

Иными словами, нужно получить данные о доме, если у пользователя есть к нему доступ.

Привязки

Phoenix поддерживает привязки к элементам DOM для взаимодействия клиента с сервером. Например, чтобы реагировать на нажатие кнопки, нужно отобразить элемент:

<button phx-click="inc_temperature">+</button>

На сервере все привязки LiveView обрабатываются обратным вызовом handle_event/3, например:

def handle_event("inc_temperature", _value, socket) do
  {:noreply, update(socket, :temperature, &(&1 + 1))}
end

Для обновления состояния интерфейса, например для открытия и закрытия раскрывающихся списков, переключения вкладок и т. д., LiveView также поддерживает команды JS (Phoenix.LiveView.JS), которые выполняются непосредственно на клиенте, не обращаясь к серверу. Подробнее см. на странице о привязках — полный список всех привязок LiveView — и в руководстве по взаимодействию с JavaScript.

LiveView имеет встроенную поддержку форм, включая загрузку файлов и управление связями. В качестве отправной точки ознакомьтесь с разделом Phoenix.Component.form/1, а для работы со связями — с разделом Phoenix.Component.inputs_for/1. В руководствах «Загрузка файлов» и «Привязки форм» приведены дополнительные сведения о расширенных возможностях.

Навигация

LiveView позволяет переходить между страницами с помощью API pushState браузера. При живой навигации страница обновляется без полной перезагрузки.

Можно либо изменить текущий LiveView, обновив его URL, либо перейти к новому LiveView. Подробнее об этих возможностях читайте в руководстве «Живая навигация».

Генераторы

В Phoenix v1.6 и более поздних версиях есть генераторы кода для LiveView. Чтобы увидеть пример структуры приложения — от базы данных до LiveView, — выполните следующую команду в проекте LiveView:

$ mix phx.gen.live Blog Post posts title:string body:text

Дополнительную информацию можно получить, выполнив mix help phx.gen.live.

Чтобы настроить аутентификацию со встроенной поддержкой LiveView, выполните mix phx.gen.auth Account User users.

Разделение состояния, разметки и событий в LiveView

LiveView поддерживает два механизма расширения: функциональные компоненты, предоставляемые шаблонами HEEx, и компоненты с состоянием, известные как LiveComponents.

Функциональные компоненты для организации разметки и обработки событий

Подобно render(assigns) в LiveView, функциональный компонент — это любая функция, которая получает карту assigns и возвращает шаблон ~H. Например:

def weather_greeting(assigns) do
  ~H"""
  <div title="My div" class={@class}>
    <p>Hello {@name}</p>
    <MyApp.Weather.city name="Kraków"/>
  </div>
  """
end

Подробнее о функциональных компонентах читайте в модуле Phoenix.Component. В конечном счёте они служат полезным механизмом для организации кода и повторного использования разметки в LiveView.

Иногда между LiveView нужно совместно использовать не только разметку. Если вы также хотите вынести обработку событий в отдельный модуль или использовать один и тот же обработчик событий в нескольких местах, функциональные компоненты можно сочетать с Phoenix.LiveView.attach_hook/4.

Live-компоненты для инкапсуляции дополнительного состояния

Иногда компоненту требуется управлять не только собственными событиями, но и отдельным состоянием. Для таких случаев LiveView предоставляет Phoenix.LiveComponent, которые отображаются с помощью live_component/1:

<.live_component module={UserComponent} id={user.id} user={user} />

У LiveComponents есть собственные обратные вызовы mount/1 и handle_event/3, а также собственное состояние с поддержкой отслеживания изменений, как и у LiveView. Они легковесны, поскольку «работают» в том же процессе, что и родительский LiveView, но сложнее самих функциональных компонентов. Поскольку все они работают в одном процессе, ошибки в компонентах приводят к сбою при отрисовке всего представления. Полный обзор приведён в разделе Phoenix.LiveComponent.

Если вы не уверены, что выбрать — функциональные компоненты или live-компоненты, — по умолчанию выбирайте первые. Используйте вторые, только когда требуется дополнительное состояние.

live_render/3 для инкапсуляции состояния (с изоляцией ошибок)

Наконец, если требуется полная изоляция частей LiveView, можно отобразить один LiveView внутри другого, вызвав live_render/3. Этот дочерний LiveView выполняется в отдельном от родительского процессе и имеет собственные обратные вызовы. Сбой дочернего LiveView не повлияет на родительский. При сбое родительского процесса все дочерние процессы завершаются.

При отображении дочернего LiveView требуется параметр :id, чтобы уникально идентифицировать дочерний элемент. Дочерний LiveView отображается и монтируется только один раз, пока его идентификатор остаётся неизменным. Чтобы принудительно смонтировать его заново с новыми данными сессии, необходимо указать новый идентификатор.

Поскольку вложенный LiveView работает в собственном процессе, это отличный инструмент для создания полностью изолированных элементов интерфейса. Однако это несколько затратная абстракция, если нужно лишь разделить разметку или обработку событий (или и то и другое).

Итоги

  • используйте Phoenix.Component для организации кода и повторного использования разметки (при необходимости сочетая их с attach_hook/4 для повторного использования обработки событий)
  • используйте Phoenix.LiveComponent для совместного использования состояния, разметки и событий между LiveView
  • используйте вложенные Phoenix.LiveView для разделения состояния, разметки и событий (с изоляцией ошибок)

Руководства

Документация разделена на две категории. Справочник по API содержит сведения обо всех модулях LiveView, в нём вы подробнее узнаете о Phoenix.Component, Phoenix.LiveView и других модулях.

В LiveView также есть множество руководств, которые помогут вам в работе. Они разделены на материалы по серверной и клиентской частям:

Серверная часть

Эти руководства посвящены функциональности серверной части:

  • Assigns и шаблоны HEEx
  • Развёртывание и восстановление
  • Обработка ошибок и исключений
  • Gettext для интернационализации
  • Макеты LiveView
  • Живая навигация
  • Вопросы безопасности
  • Телеметрия
  • Загрузка файлов

Клиентская часть

Эти руководства посвящены привязкам LiveView и интеграции на стороне клиента:

  • Привязки
  • Внешняя загрузка файлов
  • Привязки форм
  • Взаимодействие с JavaScript
  • Синхронизация изменений и оптимистичные интерфейсы
← Предыдущая страница Список изменений v1.2
Следующая страница → Assigns и шаблоны HEEx

Пакет Hex Предпросмотр Hex (текущий файл) Просмотреть llms.txt Скачать версию ePub

Создано с помощью ExDoc (v0.40.3) для языка программирования Elixir

© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix-live-view.hexdocs.pm/welcome.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API