• Шаблоны для вашего сайта
  • Сделать сайт
  • Реклама
  • Berry CSS
  • Albireo Framework
  • Бесплатный HTML-курс
  • Telegram-канал
  • Обратная связь
MaxSite.org
О создании сайтов и не только
Создание сайтов под ключ (Украина) →
Вход
×
или зарегистрироваться

Взаимодействие между Alpine-компонентами

Alpine.jsПросмотров: 2442Комментарии: 76 января 2021 г.

Как мы знаем, все компоненты Alpine работают изолировано. Директива x-data определяет сам компонент и всё «реактивное» взаимодействие происходит в пределах данного блока.

Но что делать, если нужно организовать связь между несколькими компонентами? Формально мы можем использовать сторонний js-код, в котором хранить общие переменные. Или даже использовать LocalStorage, чтобы сохранять состояние после закрытия страницы. Но всё это скорее обходные манёвры. Попробуем сделать это на нативном функционале Alpine.js.

Вообще зачем это нужно? Представим себе, что у нас есть страница, где несколько div-блоков, которые из соображений вёрстки нельзя разместить в одном родителе. Например будет ряд кнопок, нажав на которые будет выводиться блок сообщения. Причем пусть каждая кнопка должна ещё передавать дополнительные параметры, например css-класс.

Стандартно такой механизм в JavaScript называется пользовательские события (CustomEvent). То есть идея в том, что кнопки будут генерировать какое-то событие, а блок сообщения его перехватывать.

В Alpine для этого можно использовать магические свойства $dispatch и $event. Первое — это генерация события, второе — его получение.

Рассмотрим базовый пример. Вначале полный код:

<button x-data @click="$dispatch('myevent1', {show: 'open', tclass: 't-red'})">show red</button>
 
<button x-data @click="$dispatch('myevent1', {show: 'open', tclass: 't-blue'})">show blue</button>
 
<button x-data @click="$dispatch('myevent1', {show: 'hide', tclass: 'b-hide'})">hide</button>
 
<div x-data="{show: '-', tclass: '-'}" @myevent1.window="show = $event.detail.show; tclass = $event.detail.tclass">
	<div x-text="'Status: ' + show"></div>
	<div x-text="'Class: ' + tclass" :class="tclass"></div>
</div>

Все блоки представляют собой независимые Alpine-компоненты. У кнопок мы цепляемся за событие onclick. По клику будет выполняться магический метод/функция $dispatch(). Первый параметр — это имя генерируемого события, второй — его произвольные данные.

Блок сообщения (DIV) будет принимать это событие. Код @myevent1.window — это перехват события (сокращённая запись x-on:), где .window указывает на перехват «глобального» window-события.

То есть как только появится событие myevent1, сработает данный код. В нём $event это «стандартный» объект js-события, только через detail возвращает переданные данные. В данном случае это show и tclass события, которые мы присваиваем текущему компоненту.

Дальше мы работаем с данными компонента как обычно.

Небольшое замечание по поводу передаваемых данных. Не нужно передавать булевые значения (true и false). В процессе передачи (в некоторых случаях - из полей форм) они преобразуются в строки 'true' и 'false', а значит код x-show="show" всегда будет возвращать логическое true, поскольку Boolean('false') равен true.

Рассмотрим ещё один пример того, как можно создавать события от полей ввода, где используется x-model. Вначале полный код примера:

<div x-data="{show: ''}" @myevent2.window="show = $event.detail.show">
	<div x-show="show == 'show'">message</div>
</div>
 
<div x-data="{s: 'hide'}" x-init="$watch('s', value => $dispatch('myevent2', {show: value}))">
    <select x-model="s">
	    <option value="hide">hide</option>
        <option value="show">show</option>    
    </select>
</div>

Блок «message» ловит пользовательское событие myevent2, по которому задаётся переменная show. На неё завязано отображения блока с помощью x-show.

Блок «select» более сложный. Вначале мы связываем поле ввода через переменную s. Поскольку это «реактивность», то код очень простой. Для того, чтобы отправить событие через $dispatch нам нужно прицепиться к какому-то событию, например onchange для SELECT и сделать аналогично примеру с кнопками.

Такой вариант неплох для простого html-кода, если же у нас более сложная вёрстка, то по возможности лучше её упростить. К тому же у нас уже есть «реактивность» из «коробки» Alpine, поэтому оптимальным вариант — это генерировать событие, как только изменится переменная s (по любому поводу).

Здесь Alpine предлагает ещё одно магическое свойство $watch — функция, которая отслеживает изменение любой переменной компонента. То есть как только s изменится (помним, что она «реактивная» за счёт x-model), сработает $watch, который выполнит код, где мы и пропишем генерацию события с помощью $dispatch().

message

Ещё один вопрос, который стоит рассмотреть. Можем ли мы повлиять на принимаемый компонент — передать ему некие «начальные» данные. Скажем в примере с кнопками мы хотим передать другой класс и статус видимости.

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

<div x-data @load.window="$dispatch('myevent1', {show: 'open', tclass: 't-green'})"></div>

То есть сразу после загрузки страницы этот код сгенерирует событие с нужными данными. Как ни странно, но такой подход заменяет довольно сложный js-код. :-)


Создание сайтов (Украина) →
Обновление Albireo Framework (январь 2021)
Итоги 2020 года
twitter.com facebook.com
Другие записи сайта
Контекстные ссылки: за и против
Контекстные ссылки: за и против
Сайту 6 лет!
Сайту 6 лет!
База SQLite и основы SQL. Часть 9
База SQLite и основы SQL. Часть 9
Как выключать Windows?
Как выключать Windows?
Учимся работать с шаблоном MF. Модули главной
Учимся работать с шаблоном MF. Модули главной
Программа для кодера - Notepad2
Программа для кодера - Notepad2

Комментариев: 7 RSS

1Bugo22-02-2021 09:59

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

https://codepen.io/dragomano/pen/eYmXrrP

2MAX22-02-2021 10:06

У ссылки отправляете событие

$dispatch('myevent1'...

У принимающего SPAN ловите

@myevent1.window="...

События у каждой пары A/SPAN должны быть индивидуальные.

3Bugo22-02-2021 10:31

Это понятно, но если в таблице строк 10+, 100+ и так далее, а в названиях событий почему-то не поддерживаются цифры (то есть я не могу почему-то использовать названия типа "myevent" + id строки), неужели придется генерировать случайные названия для каждой строки?

4Bugo22-02-2021 10:37

Разобрался. Я называл события так: "my_event_1", а нужно так: "myevent1" :)

https://codepen.io/dragomano/pen/eYmXrrP

5MAX22-02-2021 10:39

Ну вы сами придумали такую схему. :-)

Архитектурно такой алгоритм неверный. Нужно всю таблицу сделать одним компонентом, а каждую строку TR выводить в цикле TEMPLATE, где есть свой счётчик к которому можно привязаться. Да и события в такой схеме просто не нужны.

6Bugo22-02-2021 10:45

Шаблон предоставляется CMS, я могу влиять только на содержимое ячеек (td), приходится изворачиваться :)

7MAX22-02-2021 10:49

В теории можно использовать для всех одно событие, но в свойствах события передавать ID. Но это всё равно нужно проставлять их уникальными. Иначе невозможно будет различать пары между собой.

Оставьте комментарий!

Комментарий будет опубликован после проверки. Вы соглашаетесь с правилами сайта.

(обязательно)

Навигация
  • Шаблоны для MaxSite CMS 22
  • jQuery и JavaScript 6
  • Java и Android 5
  • PHP/ООП 25
  • SQL 17
  • Albireo Framework 11
  • Berry CSS 7
  • CSS, HTML, LESS, SASS 23
  • PHP 37
  • Тайм-менеджмент 9
  • Софт 37
  • SEO 13
  • Git. GitHub 3
  • CodeIgniter 5
  • Landing Page 3
  • Alpine.js 14
  • Фильмы 2
  • Дневник 55

Здесь можно заказать создание сайта (только Украина), шаблона или лендинга. Также вы можете выбрать готовые шаблоны для MaxSite CMS по небольшой цене. Также можно купить отдельные модули, компоненты для вашего сайта.

MaxSite.org
Как создать свой сайт

Услуги по созданию сайтов, блогов, лендингов
Обратная связь • Реклама на сайте
Карта сайта
Мои проекты
  • Шаблоны для вашего сайта
  • Заказать создание сайта
  • MaxSite CMS
  • Berry CSS (CSS Utilities)
  • Albireo Framework
  • UniCSS (Universal Atomic CSS)
  • Landing Page Framework
  • Бесплатные НТML-курсы
Ссылки
  • Telegram-канал
  • Github
  • Twitter
  • Telegram-бот
  • RSS
© MaxSite.org, 2006-2022. Работает на MaxSite CMS | Время: 0.2815 | SQL: 20 | Память: 4.63MB | Вход