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

x-on

x-on позволяет вам легко запускать код для отправленных событий DOM.

Вот пример простой кнопки, при нажатии на которую отображается предупреждение.

<div x-data>
<button x-on:click="alert('Привет, мир!')">Скажи привет</button>
</div>

Сокращённый синтаксис

Если x-on: вам кажется слишком многословным, вы можете использовать сокращённый синтаксис: @.

Вот тот же компонент, что и выше, но с использованием сокращённого синтаксиса:

<button @click="alert('Привет, мир!')">Скажи привет</button>

Объект события

Если вы хотите получить доступ к собственному объекту события JavaScript из вашего выражения, вы можете использовать магическое свойство Alpine $event.

<div x-data>
<button @click="alert($event.target.getAttribute('message'))" message="Привет, мир!">
Скажи привет
</button>
</div>

Кроме того, Alpine также передаёт объект события всем методам, на которые он ссылается, без завершающих круглых скобок. Например:

<button @click="handleClick">...</button>
<script>
function handleClick(event) {
// Теперь вы можете напрямую получить доступ к объекту события (event).
}
</script>

События клавиатуры

Alpine позволяет легко прослушивать события keydown и keyup на определённых клавишах.

Вот пример прослушивания клавиши Enter внутри элемента ввода.

<div x-data>
<input type="text" @keyup.enter="alert('Отправлено!')" />
</div>

Вы также можете объединить эти ключевые модификаторы для создания более сложных слушателей.

Вот слушатель, который запускается, когда удерживается клавиша Shift и нажимается Enter:

<input type="text" @keyup.shift.enter="alert('Отправлено!')" />

Вы можете напрямую использовать любые действительные имена ключей, предоставленные через KeyboardEvent.key, в качестве модификаторов, преобразовав их в шашлычную нотацию (kebab-case).

<input type="text" @keyup.page-down="alert('Отправлено!')" />

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

МодификаторКлавиша клавиатуры
.shiftShift
.enterEnter
.spaceПробел
.ctrlCtrl
.cmdCmd
.metaклавиша Windows (Cmd в Mac)
.altAlt
.up .down .left .rightстрелки Up/Down/Left/Right
.escapeEscape
.tabTab
.caps-lockCaps Lock
.equalзнак равно, =
.periodточка, .
.commaзапятая, ,
.slashкосая черта, /

События мыши

Как и в случае с вышеупомянутыми событиями клавиатуры, Alpine позволяет использовать некоторые модификаторы клавиш для обработки событий click:

МодификаторКлавиша события
.shiftshiftKey
.ctrlctrlKey
.cmdmetaKey
.metametaKey
.altaltKey

Они работают с событиями click, auxclick, context и dblclick, а также с mouseover, mousemove, mouseenter, mouseleave, mouseout, mouseup и mousedown.

Вот пример кнопки, поведение которой меняется при нажатии клавиши Shift:

<div x-data="{ message: '' }">
<button type="button"
@click="message = 'выбрано'"
@click.shift="message = 'добавлено в выбранные'"
@mousemove.shift="message = 'добавить к выбору'"
@mouseout="message = 'выбрать'"
x-text="message"></button>
</div>

Пользовательские события

Слушатели событий Alpine — это оболочка для собственных слушателей событий DOM. Таким образом, они могут прослушивать ЛЮБЫЕ события DOM, включая пользовательские события.

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

<div x-data @foo="alert('Кнопка была нажата!')">
<button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">
...
</button>
</div>

При нажатии кнопки будет вызван слушатель @foo.

Так как API .dispatchEvent многословен, Alpine предлагает хелпер $dispatch для упрощения работы.

Вот тот же компонент, переписанный с помощью магического свойства $dispatch:

<div x-data @foo="alert('Кнопка была нажата!')">
<button @click="$dispatch('foo')">...</button>
</div>

Модификаторы

Alpine предлагает ряд модификаторов директив для настройки поведения слушателей событий.

.prevent

.prevent эквивалентен вызову .preventDefault() внутри слушателя объекта события браузера.

<form @submit.prevent="console.log('отправлено')" action="/foo">
<button>Отправить</button>
</form>

В приведённом выше примере с .prevent нажатие кнопки НЕ приведет к отправке формы в конечную точку /foo. Вместо этого слушатель Alpine обработает его и «предотвратит» дальнейшую обработку события.

.stop

Подобно .prevent, .stop является эквивалентом вызова .stopPropagation() внутри слушателя объекта события браузера.

<div @click="console.log('Вы не увидите это сообщение')">
<button @click.stop>Нажми меня</button>
</div>

В приведённом выше примере нажатие кнопки НЕ зарегистрирует сообщение. Это связано с тем, что мы немедленно прекращаем распространение события и не позволяем ему «всплывать» до <div> с слушателем @click.

.outside

.outside — это удобный помощник для прослушивания щелчка за пределами элемента, к которому он прикреплён. Вот простой пример компонента раскрывающегося списка:

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

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

Это связано с тем, что .outside прослушивает клики, которые НЕ исходят от элемента, на котором он зарегистрирован.

.window

Если присутствует модификатор .window, Alpine зарегистрирует слушатель событий в корневом объекте window на странице, а не в самом элементе:

<div @keyup.escape.window="...">...</div>

Приведённый выше фрагмент будет прослушивать нажатие клавиши «Escape» В ЛЮБОМ месте на странице.

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

.document

.document работает аналогично .window, только он регистрирует слушателей в глобальном document, а не в глобальном window.

.once

Добавляя .once к слушателю, вы гарантируете, что обработчик будет вызываться только ОДИН РАЗ:

<button @click.once="console.log('Я появлюсь в логе только один раз')">...</button>

.debounce

Иногда полезно «отключить» обработчик событий, чтобы он вызывался только после определённого периода бездействия (по умолчанию 250 миллисекунд).

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

<input @input.debounce="fetchResults" />

Теперь вместо вызова fetchResults после каждого нажатия клавиши, fetchResults будет вызываться только после 250 миллисекунд отсутствия нажатий клавиш.

Если вы хотите увеличить или сократить время устранения дребезга, вы можете сделать это, проставив продолжительность после модификатора .debounce следующим образом:

<input @input.debounce.500ms="fetchResults" />

Теперь fetchResults будет вызываться только после 500 миллисекунд бездействия.

.throttle

.throttle похож на .debounce, за исключением того, что он будет вызывать вызов обработчика каждые 250 миллисекунд вместо того, чтобы откладывать его на неопределённый срок.

Это полезно в случаях, когда могут повторяться и длиться события, и использование .debounce не будет работать, потому что вы все равно хотите время от времени обрабатывать событие.

Например:

<div @scroll.window.throttle="handleScroll">...</div>

Приведённый выше пример — отличный вариант использования регулирования. Без .throttle метод handleScroll будет запускаться сотни раз, когда пользователь прокручивает страницу вниз. Это может сильно замедлить работу сайта. Добавляя .throttle, мы гарантируем, что handleScroll будет вызываться каждые 250 миллисекунд.

Как и в случае с .debounce, вы можете добавить собственную длительность регулируемого события:

<div @scroll.window.throttle.750ms="handleScroll">...</div>

Теперь handleScroll будет вызываться каждые 750 миллисекунд.

.self

Добавляя .self к слушателю событий, вы гарантируете, что событие возникло в элементе, в котором оно объявлено, а не в дочернем элементе.

<button @click.self="handleClick">
Нажми меня
<img src="..." />
</button>

В приведённом выше примере у нас есть тег <img> внутри тега <button>. Обычно любой щелчок, происходящий внутри элемента <button> (например, в <img>), будет обнаружен слушателем @click на кнопке.

Однако в этом случае, поскольку мы добавили .self, только нажатие на кнопку вызовет handleClick. Не будут обрабатываться только клики, происходящие на элементе <img>.

.camel

<div @custom-event.camel="handleCustomEvent">...</div>

Иногда вам может потребоваться прослушивать события camelCased, такие как customEvent в нашем примере. Поскольку camelCasing внутри HTML-атрибутов не поддерживается, Alpine необходимо добавить модификатор .camel для внутреннего использования camelCase имени события.

Добавив .camel в приведённом выше примере, Alpine теперь прослушивает customEvent вместо custom-event.

.dot

<div @custom-event.dot="handleCustomEvent">...</div>

Подобно модификатору .camelCase, могут возникнуть ситуации, когда вы захотите прослушивать события, в имени которых есть точки (например, custom.event). Поскольку точки в названии события зарезервированы Alpine, вам необходимо писать их через тире и добавлять модификатор .dot.

В приведённом выше примере кода custom-event.dot будет соответствовать имени события custom.event.

.passive

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

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

<div @touchstart.passive="...">...</div>

.capture

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

<div @click.capture="console.log('Я зарегистрируюсь первым')">
<button @click="console.log('Я зарегистрируюсь вторым')"></button>
</div>

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

  1. Как перехватить нажатие пробела?

  2. Какой из вариантов кода подойдет для прослушивания события ohMyGosh?