Перейти к содержимому

Первые шаги

  1. Создайте где-нибудь на компьютере пустой HTML-файл с именем типа i-love-alpine.html

  2. Используя текстовый редактор, заполните файл таким содержимым:

    <html>
    <head>
    <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js"></script>
    </head>
    <body>
    <h1 x-data="{ message: 'Я ❤️ Alpine' }" x-text="message"></h1>
    </body>
    </html>
  3. Откройте свой файл в браузере — если вы увидите Я ❤️ Alpine, то можете продолжать!

Теперь, когда всё готово к работе, давайте рассмотрим три практических примера для обучения основам Alpine. К концу этого упражнения вы должны быть более чем готовы к созданию собственных проектов. Продолжим.

Создание счётчика

Давайте начнём с простого компонента «счётчик», чтобы продемонстрировать основы состояния и прослушивания событий в Alpine — двух базовых функций.

Вставьте следующее в тег <body>:

<div x-data="{ count: 0 }">
<button x-on:click="count++">
Увеличить счётчик
<span x-text="count"></span>
</button>
</div>

Теперь вы можете видеть, что с помощью 3 кусочков Alpine, добавленных в этот HTML, мы создали интерактивный компонент «счётчик».

Давайте вкратце рассмотрим происходящее:

Объявление данных

<div x-data="{ count: 0 }"></div>

Всё в Alpine начинается с директивы x-data. Внутри x-data на обычном JavaScript объявляется объект данных, который будет отслеживаться Alpine.

Каждое свойство этого объекта будет доступно другим директивам внутри данного HTML-элемента. Кроме того, при изменении одного из этих свойств меняется и всё, что на него опирается.

Давайте посмотрим на x-on и разберёмся, как он может получить доступ к свойству count для чтения и изменения:

Прослушивание событий

<button x-on:click="count++">Увеличить счётчик</button>

x-on — это директива, которую можно использовать для прослушивания любого события на элементе. В данном случае мы слушаем событие click, поэтому наш вариант выглядит как x-on:click.

Можно прослушивать и другие события, как вы предполагаете. Например, прослушивание события mouseenter будет выглядеть следующим образом: x-on:mouseenter.

Когда происходит событие click, Alpine вызывает связанное с ним JavaScript-выражение, в нашем случае count++. Как видите, мы имеем прямой доступ к данным, объявленным в выражении x-data.

Реагирование на изменения

<span x-text="count"></span>

x-text — это директива Alpine, которую вы можете использовать для установки текстового содержимого элемента в результат выражения JavaScript.

В данном случае мы указываем Alpine на то, что содержимое тега span всегда должно отражать значение свойства count.

Если не понятно, то x-text, как и большинство директив, принимает в качестве аргумента обычное JavaScript-выражение. Так, например, вместо этого можно задать его содержимое в виде: x-text="count * 2" и текстовое содержимое span теперь всегда будет в 2 раза больше значения count.

Создание спойлера

Теперь, когда мы познакомились с базовой функциональностью, давайте продолжим и рассмотрим важную директиву в Alpine: x-show, создав компонент «спойлер».

Вставьте в тег <body> следующий код:

<div x-data="{ open: false }">
<button @click="open = !open">Переключить</button>
<div x-show="open" @click.outside="open = false">Содержимое...</div>
</div>
Содержимое...

Если вы загрузите этот компонент, вы увидите, что «Содержимое…» по умолчанию скрыто. Для отображения скрытого содержимого нужно нажать кнопку «Переключить».

Директивы x-data и x-on должны быть знакомы вам по предыдущему примеру, поэтому мы опустим эти пояснения.

Переключение элементов

<div x-show="open" ...>Содержимое...</div>

x-show — чрезвычайно мощная директива в Alpine, которую можно использовать для отображения и скрытия блока HTML на странице на основе результата выражения JavaScript, в нашем случае: open.

Прослушивание клика за пределами указанного элемента

<div ... @click.outside="open = false">Содержимое...</div>

В этом примере вы заметите кое-что новое: .outside. Многие директивы в Alpine принимают «модификаторы», которые прикрепляются к концу директивы и разделяются точками.

В данном случае .outside указывает Alpine на то, что вместо того, чтобы ожидать клик мыши ВНУТРИ <div>, нужно ожидать клик мыши только в том случае, если он происходит ВНЕ <div>.

Это удобный помощник, встроенный в Alpine, поскольку такая необходимость встречается часто, а реализовывать её вручную неудобно и сложно.

Создание поля поиска

Теперь построим более сложный компонент и введём несколько других директив и паттернов.

Вставьте в тег <body> следующий код:

<div
x-data="{
search: '',
items: ['foo', 'bar', 'baz'],
get filteredItems() {
return this.items.filter(
i => i.startsWith(this.search)
)
}
}"
>
<input x-model="search" placeholder="Поиск...">
<ul>
<template x-for="item in filteredItems" :key="item">
<li x-text="item"></li>
</template>
</ul>
</div>

По умолчанию все «элементы» (foo, bar и baz) будут отображаться на странице, но вы можете отфильтровать их, введя текст в поле ввода. По мере ввода список элементов будет меняться в зависимости от того, что вы ищете.

Здесь происходит немало событий, поэтому давайте пройдёмся по этому фрагменту по частям.

Многострочное форматирование

Первое, на что хотелось бы обратить внимание, это то, что в x-data теперь происходит гораздо больше событий, чем раньше. Для удобства написания и чтения мы разбили его на несколько строк в нашем HTML. Это совершенно необязательно, и мы ещё поговорим о том, как избежать этой проблемы, а пока оставим весь этот JavaScript непосредственно в HTML.

Привязка к полям

<input x-model="search" placeholder="Поиск..." />

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

x-model используется для «привязки» значения входного элемента к свойству данных: в нашем случае «search» из x-data="{ search: '', ... }".

Это означает, что каждый раз, когда значение ввода изменяется, значение «поиск» будет меняться, чтобы отразить это.

x-model способна на гораздо большее, чем этот простой пример.

Вычисляемые свойства с использованием геттеров

Следующий момент, на который я хотел бы обратить ваше внимание — это свойства items и filteredItems из директивы x-data.

{
...
items: ['foo', 'bar', 'baz'],
get filteredItems() {
return this.items.filter(
i => i.startsWith(this.search)
)
}
}

Свойство items не требует пояснений. Здесь мы устанавливаем значение items в массив JavaScript, состоящий из 3 различных элементов (foo, bar и baz).

Интересной частью этого фрагмента является свойство filteredItems.

Обозначаемый префиксом get для этого свойства, filteredItems является «getter»-свойством в этом объекте. Это означает, что мы можем получить доступ к фильтруемым элементам, как если бы это было обычное свойство нашего объекта данных, но когда мы это сделаем, JavaScript выполнит запуск предоставленной функции и вернёт результат.

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

Теперь заглянем в геттер filteredItems и убедимся, что мы понимаем, что там происходит:

return this.items.filter((i) => i.startsWith(this.search));

Это всё простой JavaScript. Сначала мы получаем массив элементов (foo, bar и baz) и фильтруем их, используя предоставленный обратный вызов: i => i.startsWith(this.search).

Передавая этот обратный вызов в filter, мы говорим JavaScript, чтобы он возвращал только те элементы, которые начинаются со строки: this.search, которая, как мы видели с x-model, всегда будет отражать значение поля ввода.

Вы можете заметить, что до сих пор нам не приходилось использовать this для ссылки на свойства. Однако, поскольку мы работаем непосредственно внутри объекта x-data, мы должны ссылаться на любые свойства, используя this.[property] вместо [property].

Потому что Alpine — это «реактивный» фреймворк. При каждом изменении значения this.search части шаблона, использующие filteredItems, будут автоматически обновляться.

Повторение элементов

Теперь, когда мы разобрались с внутренней частью нашего компонента, давайте поймем, что происходит в шаблоне, который позволяет нам перебирать filteredItems на странице.

<ul>
<template x-for="item in filteredItems">
<li x-text="item"></li>
</template>
</ul>

Первое, на что следует обратить внимание, — это директива x-for. Выражения x-for имеют следующий вид: [item] in [items], где [items] — произвольный массив данных, а [item] — имя переменной, которой будет присвоена итерация внутри цикла.

Также обратите внимание, что x-for объявляется на элементе <template>, а не непосредственно на <li>. Это является обязательным условием использования x-for. Это позволяет Alpine использовать существующее поведение тегов <template> в браузере в своих интересах.

Теперь любой элемент внутри тега <template> будет повторяться для каждого элемента внутри filteredItems, а все выражения, вычисляемые внутри цикла, будут иметь прямой доступ к итерационной переменной (в данном случае item).

Проверка знаний

  1. Самая важная директива в Alpine.js…

  2. Нажатие на какую из кнопок приведёт к переключению спойлера?

    <div x-data="{ open: false }">
    // код кнопки
    <div x-show="open" @click.outside="open = false">Содержимое...</div>
    </div>
  3. Синтаксис геттеров внутри объекта x-data выглядит как…

Итоги

Если вы дошли до этого момента, значит, в Alpine вы познакомились со следующими директивами:

  • x-data
  • x-on
  • x-text
  • x-show
  • x-model
  • x-for

Это отличное начало, однако есть ещё много нюансов, в которые стоит вникнуть. Лучший способ освоить Alpine — прочитать эту документацию. Не нужно прочёсывать каждое слово, но если вы хотя бы просмотрите каждую страницу, то будете НАМНОГО эффективнее использовать Alpine.

Приятного кодирования!