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

x-data

В Alpine всё начинается с директивы x-data.

x-data определяет фрагмент HTML как компонент Alpine и предоставляет реактивные данные для ссылки на этот компонент.

Приведём пример выпадающего компонента:

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

Не обращайте внимания на другие директивы в этом примере (@click и x-show), к ним мы перейдем чуть позже. Пока остановимся на x-data.

Область видимости

Свойства, определённые в директиве x-data, доступны всем дочерним элементам. Даже внутри других вложенных компонентов x-data.

Например:

<div x-data="{ foo: 'bar' }">
<span x-text="foo"><!-- Отрендерит как: "bar" --></span>
<div x-data="{ bar: 'baz' }">
<span x-text="foo"><!-- Отрендерит как: "bar" --></span>
<div x-data="{ foo: 'bob' }">
<span x-text="foo"><!-- Отрендерит как: "bob" --></span>
</div>
</div>
</div>

Методы

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

Например, давайте выделим поведение «Переключить содержимое» в метод x-data.

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

Обратите внимание на добавление метода toggle() { this.open = !this.open } внутри x-data. Теперь этот метод может быть вызван из любого места внутри компонента.

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

При желании можно полностью отказаться от вызывающей скобки в методе toggle. Например:

<!-- До -->
<button @click="toggle()">...</button>
<!-- После -->
<button @click="toggle">...</button>

Геттеры

Геттеры JavaScript удобны, когда единственной целью метода является возврат данных на основе другого состояния.

Думайте о них как о «вычисляемых свойствах» (правда, они не кэшируются) Vue.

Давайте отрефакторим наш компонент, чтобы использовать геттер isOpen вместо прямого обращения к open.

<div
x-data="{
open: false,
get isOpen() { return this.open },
toggle() { this.open = !this.open },
}"
>
<button @click="toggle()">Переключить содержимое</button>
<div x-show="isOpen">Содержимое...</div>
</div>
Содержимое...

Обратите внимание, что «содержимое» теперь зависит от геттера isOpen, а не от свойства open напрямую.

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

Компоненты без данных

Иногда возникает необходимость создать компонент Alpine, но при этом не требуется никаких данных.

В этих случаях всегда можно передать пустой объект.

<div x-data="{}"></div>

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

<div x-data></div>

Одноэлементные компоненты

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

<div x-data="{ open: true }">
<button @click="open = false" x-show="open">Скрыть меня</button>
</div>

В этих случаях можно объявить x-data непосредственно на этом отдельном элементе:

<button
x-data="{ open: true }"
@click="open = false" x-show="open"
>Скрыть меня</button>

Переиспользуемые данные

Если вы обнаружите, что дублируете содержимое x-data или считаете синтаксис строки многословным, вы можете извлечь объект x-data в специальный компонент с помощью Alpine.data.

Приведём небольшой пример:

<div x-data="dropdown">
<button @click="toggle">Переключить содержимое</button>
<div x-show="open">Содержимое...</div>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('dropdown', () => ({
open: false,
toggle() {
this.open = !this.open;
},
}));
});
</script>
Содержимое...

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

  1. Свойства, определённые в директиве x-data

    <div x-data="...">
    <div x-data="...">
    <div x-data="..."></div>
    </div>
    </div>
  2. Как определить компонент Alpine.js без каких-либо данных?