Svelte: знакомимся с Действиями
Недавно на Хабре появилась статья от @sanReal, где Александр рассказал о том, каким приёмам и каким возможностям Svelte он научился на собственном опыте. Я был немного удивлён не увидев в его списке упоминания одного из самых мощных инструментов фреймворка — Действий. К тому же, общаясь с людьми в сообществе @sveltejs, которые уже создают очень хорошие приложения при помощи Svelte, я иногда замечаю, что не все пользуются Действиями даже там, где их применение идеально решало бы задачу. В этой статье я расскажу, что такое Действия и на простейших примерах покажу их применение.
Предположим, у нас есть текстовое поле, в которое пользователь должен ввести номер телефона. Нам нужно добиться того, чтобы пользователь смог ввести в поле только цифры.
Телефон: +7
Когда встречается задача наделить стандартный HTML-элемент дополнительными возможностями, обычной практикой при работе в любом компонентом фреймворке будет создание переиспользуемого компонента вокруг этого элемента, внутри которого реализуется логика нестандартного поведения. Так же можно поступить и в Svelte:
...
Телефон: +7
Посмотреть в действии
Задача выполнена, но сам элемент теперь спрятан внутри компонента, поэтому мы больше не сможем манипулировать им как обычным HTML-элементом — «навесить» на него какие-либо CSS-классы, обработчики событий или какие-то особенные атрибуты будет уже не так просто.
Для подобных случаев в Svelte есть свой особенный подход — Действия (в английском варианте Actions). В официальном учебнике Svelte можно найти урок, посвященный этой теме, но, на мой взгляд, пример подобран несколько громоздкий — вся «соль» Действий может в нем затеряться и ускользнуть от новичков, которые выполняют этот урок. На самом же деле концепция очень простая — это что-то вроде функции жизненного цикла для любого HTML-элемента. Она вызывается, когда элемент монтируется в DOM. В качестве аргумента функция получает ссылку на соответствующий узел DOM-дерева, с которым затем и происходит вся работа.
Перепишем наш пример с использованием Действия:
Телефон: +7
Посмотреть в действии
Мы создали функцию onlydigits
, которая и будет нашим Действием. Её работа заключается в том, чтобы добавить DOM-узлу node
обработчик для события input
. Обратите внимание, что функция возвращает объект с методом destroy
, который будет вызван при удалении элемента из DOM-дерева, позволив нам убрать обработчик события с элемента и предотвратить возможные утечки памяти.
Чтобы указать Svelte, что для какого-либо HTML-элемента мы хотим использовать некое Действие, существует директива use
. В примере мы назначили Действие на элемент директивой
use:onlydigits
.
На один элемент можно назначить сразу несколько Действий. Сделаем так, чтобы пользователь не мог ввести более 10 цифр:
Телефон: +7
Посмотреть в действии
Теперь к элементу привязано два Действия —
use:onlydigits
и use:max10symbols
. Порядок вызова функций зависит от порядка объявления директив.
В директиве use
можно указать дополнительный параметр, который будет передан в функцию Действия вторым аргументом. Переработаем наш пример так, чтобы пользователь смог вводить значение только по маске. Также добавим еще одно текстовое поле для указания номера паспорта:
Телефон: +7
Паспорт:
Посмотреть в действии
Оба всё еще являются обычными HTML-элементами. К каждому из них назначена одна и та же функция Действия
format_by_pattern
, но в качестве параметра мы передаём разные маски для телефона и номера паспорта. В фигурных скобках, как и везде в шаблонах Svelte, может быть любое валидное JavaScript-выражение.
В последний раз усложним наш пример, предположив, что пользователь может вводить либо номер гражданского паспорта, либо заграничного. При выборе типа паспорта должна меняться и маска для ввода номера.
Телефон: +7
Паспорт:
- заграничный
Посмотреть в действии
Рассмотрим ближе, что тут происходит. Появился новый чекбокс, который, благодаря двусторонней привязке bind:checked
, устанавливает значение переменной zagran
в true
или false
. При переключении состояния флажка, срабатывает реактивность Svelte и тернарное выражение помещает нужную маску в параметр соответствующей директивы use:format_by_pattern
.
Однако, как мы помним, функция Действия вызывается только лишь при монтировании элемента в DOM-дерево, а при смене типа паспорта как был в DOM-дереве, так там и остаётся. Изменение значения параметра директивы не приведет к повторному вызову этой функции.
Чтобы обработать изменение параметра, нам нужно добавить в объект, который возвращает функция Действия, еще один метод — update
. Он будет вызываться всякий раз, когда изменится параметр директивы. Новое значение параметра будет передано методу в качестве аргумента.
В этой статье я показал лишь простейшее использование Действий. Но в реальности, они могут быть применены в огромном количестве различных задач. Например, упростить использование внешних библиотек, которые работают с DOM-элементами напрямую — различного рода всплывающие подсказки, автодополнения для полей ввода и прочие. С помощью Действия можно очень элегантно реализовать концепцию порталов в Svelte. Если вы уже используете Svelte на работе или для личных проектов, но до сих пор обходились без Действий, самое время попробовать.
На заметку: Совсем скоро в Москве состоится Svelte Russia Meetup #1. Регистрируйтесь, места ещё есть. Для тех кто не сможет присутствовать лично, будет организована трансляция и запись мероприятия.