Svelte: знакомимся с Действиями

Недавно на Хабре появилась статья от @sanReal, где Александр рассказал о том, каким приёмам и каким возможностям Svelte он научился на собственном опыте. Я был немного удивлён не увидев в его списке упоминания одного из самых мощных инструментов фреймворка — Действий. К тому же, общаясь с людьми в сообществе @sveltejs, которые уже создают очень хорошие приложения при помощи Svelte, я иногда замечаю, что не все пользуются Действиями даже там, где их применение идеально решало бы задачу. В этой статье я расскажу, что такое Действия и на простейших примерах покажу их применение.
d-rkgpi4gixvd4yqf208ubk3_my.png

Предположим, у нас есть текстовое поле, в которое пользователь должен ввести номер телефона. Нам нужно добиться того, чтобы пользователь смог ввести в поле только цифры.

Телефон: +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. Регистрируйтесь, места ещё есть. Для тех кто не сможет присутствовать лично, будет организована трансляция и запись мероприятия.

© Habrahabr.ru