От автора: когда вы создаете с помощью Vue динамический веб-сайт, вы, скорее всего, захотите, чтобы он мог реагировать на события. Например, если пользователь нажимает кнопку, отправляет форму или просто перемещает мышь, вы можете захотеть, чтобы ваш сайт на Vue реагировал каким-либо образом.
Обработка событий с помощью Vue
Мы можем перехватить событие, добавив директиву v-on в соответствующий элемент DOM. Допустим, мы хотим обработать нажатие на элемент кнопки — мы можем добавить следующее в шаблон Vue:
1 |
<button v-on:click="clickHandler"></button> |
Обратите внимание, что мы добавляем в директиву аргумент v-on, он будет именем события, которое мы хотим обработать (в данном случае, click).
Затем мы привязываем выражение к директиве, которая обычно будет методом, который вы хотите использовать для обработки события. В данном случае мы назвали его clickHandler.
Совет: директива v-on имеет удобное сокращение @, которое может быть использовано вместо v-on:, например: <button @click=»clickHandler»></button<.
Типы событий, которые вы можете обрабатывать
Кроме click, какие еще события DOM могут быть обработаны? Vue может обрабатывать любые виды веб- или мобильных событий (а также пользовательские события, о которых мы поговорим позже), включая: submit, keyup, drag, scroll и другие. Вот список наиболее распространенных событий DOM для справки.
Методы обработки событий
Если мы свяжем метод с директивой обработки событий, мы можем запустить некоторый пользовательский код. Мы в этом примере просто выведем сообщение на консоль, однако вы также можете сделать что-нибудь более интересное, например, отобразить / скрыть другой элемент, увеличить счетчик и т. д.
1 2 3 |
<div id="app"> <button v-on:click="clickHanlder"></button> </div> |
1 2 3 4 5 6 7 8 |
new Vue({ el: "#app", methods: { clickHandler () { console.log("You clicked the button!"); } } }) |
Объект события
Объект event передается в обработчик событий, который открывает больше возможностей для того, как вы можете реагировать на события. Этот объект содержит множество полезных свойств и методов, включая ссылку на элемент, из которого произошло событие (event.target), время возникновения события (event.timeStamp) и многое другое.
1 2 3 |
clickHandler (event) { console.log(`The button was clicked at ${event.timeStamp}.`); } |
Обратите внимание, что этот объект предоставляется собственным веб-API, а не Vue, поэтому он будет тем же объектом, который вы найдете в чистом JavaScript. Вот ссылка на интерфейс событий.
Модификаторы событий
Распространенный шаблон в приложениях JavaScript — обрабатывать отправку формы вручную, а не использовать встроенный функционал. Чтобы сделать это, вам нужно использовать перед запуском кода обработки формы нативный метод preventDefault события submit, в противном случае страница будет перенаправлена.
1 2 3 4 |
formHandler (event) { event.preventDefault(); // form handling logic } |
Вместо того, чтобы делать это вручную в обработчике, Vue предлагает модификатор события, чтобы сделать это прямо из шаблона. Обратите внимание, что модификатор добавляется после директивы.
1 |
<form @submit.prevent="formHandler"></form> |
Vue предоставляет несколько различных модификаторов событий, которые полезны в общих сценариях обработки событий:
.stop
.prevent
.capture
.self
.once
.passive
Пользовательские события
До сих пор мы говорили об обработке нативных событий. Но Vue — это основанный на компонентах фреймворк, поэтому можем ли мы заставить компонент генерировать собственное событие?
Да, и это может быть очень полезно. Допустим, вы хотите, чтобы дочерний компонент отправлял данные до родительского компонента. Здесь мы не можем использовать свойство, поскольку данные свойства передаются только от родителя к потомку, а не наоборот.
1 2 3 4 5 |
ParentComponent | | (data travels down via props, never up) v ChildComponent |
Решение заключается в том, чтобы дочерний компонент генерировал событие, а родитель прослушивал его. Для этого вызовите дочерний компонент this.$emit(«my-event»), если хотите, чтобы событие было отправлено. Например, у нас есть компонент DialogComponent, который должен сообщить своему родителю MainPage, что он был закрыт:
1 2 3 4 5 6 7 |
export default { methods: { onClose() { this.$emit("dialog-closed"); } } }; |
Затем родительский компонент может обрабатывать пользовательское событие точно так же, как и нативное событие.
1 2 3 |
<div> <dialog-component @dialog-closed="eventHandler" /> </div> |
Вы также можете отправлять данные в своем пользовательском событии, которые могут быть получены в методе обработки:
1 2 3 |
onClose() { this.$emit("dialog-closed", { time: Date.now() }); } |
1 2 3 |
eventHandler (event, { time }) { console.log(`Dialog was closed at ${time}`); } |
Совет: используйте для своих пользовательских событий имена в kebab-case! HTML нечувствителен к регистру, поэтому имя события в camel-case, например, myEvent будет в шаблоне myevent. Поэтому лучше использовать kebab-case, например, my-event и избегать путаницы.
Шина событий
Как мы увидели, дочерний компонент может отправлять событие родительскому компоненту. Но что, если вы хотите, чтобы компонент отправлял событие любому другому компоненту в иерархии?
Для этого мы можем использовать шаблон, называемый шиной событий. Здесь мы создаем отдельный экземпляр Vue для передачи события любому компоненту, который его импортирует. Сначала создайте и экспортируйте экземпляр Vue в новый файл модуля:
1 2 |
import Vue from "vue"; export default new Vue(); |
Затем импортируйте шину в компонент, в который вы хотите отправить событие. Вы можете использовать метод шины Vue $emit.
1 2 3 4 5 6 7 8 9 10 |
import eventBus from "./eventBus"; export default { ... methods: { myMethod () { eventBus.$emit("my-event") } } } |
Наконец, импортируйте шину в компонент, где вы хотите прослушивать событие. Затем вам нужно настроить прослушиватель где-то в коде. Я предлагаю вам использовать, например, хук жизненного цикла created, через него вы можете получить доступ к экземпляру компонента.
Это делается с помощью метода шины $on, который принимает два аргумента — событие, которое вы хотите прослушивать, и обратный вызов.
1 2 3 4 5 6 7 8 9 10 |
import eventBus from "./eventBus"; export default { ... created () { eventBus.$on("my-event", () => { console.log("my-event called on global event bus"); }); } } |
И вот мы это получили — способ обмена данными между любыми компонентами вашего приложения! Совет: более масштабируемое решение для передачи данных по приложению заключается в использовании Vuex.
Автор: Anthony Gore
Источник: //vuejsdevelopers.com
Редакция: Команда webformyself.