Pull to refresh

Elm. Удобный и неловкий

JavaScript *Elm *

Поговорим о Elm.


Elm — функциональный язык программирования для frontend-разработки. Синтаксис похож на Haskell, но значительно упрощен и специализирован. Исходный код на Elm компилируется в нативный JavaScript. Скомпилированный JavaScript содержит код приложения, которое управляют поддеревом DOM.


Elm. Удобный и неловкий. Композиция
Elm. Удобный и неловкий. Json.Encoder и Json.Decoder
Elm. Удобный и неловкий. Http, Task


Основным элементом в архитектуре языка Elm является приложение. В общем случае каждое приложение содержит:


  1. Состояние или модель. Данные описывающее текущее состояние приложения;
  2. Множество допустимых сообщений. Сообщения отправляются при наступлении событий (допустим клик по кнопке) и доставляются в функцию update;
  3. Функцию view, которая на основании состояния генерирует новое DOM дерево;
  4. Функция update, которая принимает модель и сообщение, а возвращает новую модель и требуемые эффекты;
  5. Функция subscribe, подписка на уведомления о событиях. В ядре языка имеются подписки на таймер, WebSocket и прочее.

Типизация


Все должно быть типизировано. Как следствие статическая проверка согласованности кода. Если скомпилировалось, то должно работать. А вот будет оно работать как вы ожидаете или нет — никаких гарантий. Это значительно упрощает рефакторинг.


Модель


Модель является пользовательским типом. Пользовательские типы строятся из:


  1. Type Aliases для описания структур;
  2. Union Types для описания допустимых объединений типов;
  3. базовые типы Int, String и прочие.

Union Types позволяют объявлять тегированные типы. Возьмем для примера описания типа User:


type User = Anonymous | User String

Объявленный тип содержит информацию о типе пользователя и его данные, если он авторизован. Иначе пользователь анонимный.


Граница


Граница между Elm runtime и внешним окружением через декодеры. Декодер (Json.Decode) — функция, которая принимает на вход JSON и возвращает Elm тип. В процессе выполнения Json.Decode.decodeString или Json.Decode.decodeValue проверяется структура входных данных и соответствие типам.


Декодер возвращает тип Result, который содержит данные, в случае успеха, или ошибку.


Представление (view)


Представление является функций от состояния, которая возвращают информацию для генерации DOM дерева. Пример:


view : Model -> Html.Html Msg
view model =
  case model.user of 
    Anonymous ->
      Html.div [] [ Html.text “Anonymous” ]

   User name ->
      Html.div [] [ Html.text (“Welcome ” ++ name) ]

Для генерации DOM узлов используются функции. В боевых проектах view представляет собой композицию из функций более общего порядка. Например:


view : Model -> Html.Html Msg
view model =
  case model.user of 
    Anonymous ->
      anonymousView

   User name ->
      userView name

anonymousView и userView пользовательские функции, которые генерируют небольшие части интерфейса.


Мутации (update)


Все события (действия пользователя, сетевые и тп) генерируют сообщения, которые доставляются в зарегистрированную при инициализации функцию. По умолчанию, эта функция имеет имя update. Функция принимает событие и модель, а возвращает новую модель и команды. Команды выполняются в Elm runtime и также могут генерировать события.


Для примера, инкремент переменной при нажатии кнопки:


update : Model -> Msg -> (Model, Cmd Msg)
update model msg =
  case msg of
    OnClick ->
      ({model | clicked = model.clicked + 1}, Cmd.none)

Подписка (subscribe)


Подписка на события происходит при старте приложения и повторно вызывается при каждом изменении модели.


В случае возникновения события они доставляются в функцию update.


Для примера, подписка на таймер с периодом 10 секунд. При достижении 10 секунд генерируется сообщение Tick и доставляется в функцию update:


subscribe : Model -> Sub Msg
subscribe model =
  Time.every 10 Tick

Источники


Tags:
Hubs:
Total votes 18: ↑14 and ↓4 +10
Views 19K
Comments Comments 8