Через props мы можем передать данные от родительского компонента в дочерний. Но что если мы хотим также передавать данные и в обратном направлении: от дочернего компонента к родителю? В этом случае необходимо определить свои события.
Общая схема создания и вызова кастомного события выглядит следующим образом. Родительский компонент устанавливает у дочернего компонента атрибут v-on:название_события:
<child-component v-on:myevent="action"></child-component&g;
Где myevent
- название события, которые мы сами определяем и которое будет отлавливать родительский компонент. А action
-
некоторы действия, которые будут вызываться при возникновении события myevent.
Дочерний компонент, в свою очередь, будет генерировать событие с помощью вызова в коде this.$emit(myevent),
где "myevent" - это имя обытия, которое отслеживает родительский компонент с помощью атрибута v-on:myevent="action"
.
Рассмотрим следующий пример:
<!DOCTYPE html> <html> <head> <title>Компоненты Vue 3</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <h2>Hello, {{name}}</h2> <useredit :user="name" v-on:userchange="change"></useredit> </div> <script src="https://unpkg.com/vue"></script> <script> const app = Vue.createApp({ data(){ return { name: 'Tom' } }, methods:{ change(value){ this.name = value; } } }); app.component('useredit', { props: ["user"], data() { return { userName: this.user} }, template: '<div><input type="text" v-model="userName" v-on:input="onUserChange" /><p>Name: {{userName}}</p></div>', methods: { onUserChange(){ this.$emit('userchange', this.userName); } } }); app.mount('#app'); </script> </body> </html>
В данном случае определяется событие userchange. В реальности в JavaScript не существует подобного события, мы его определяем сами.
В шаблоне компонента элемент ввода связан двусторонней привязкой со значением со свойством userName. Также для этого элемента установлен обработчик события input:
<input type="text" v-model="userName" v-on:input="onUserChange" />
То есть при вводе в это текстовое поле будет вызываться метод onUserChange. В этом методе через вызов this.$emit('userchange', this.userName);
генерируем событие userchange и передаем в этом событии измененное значение свойства userName (так как это свойство связано двусторонней привязкой с полем ввода, то при вводе
в текстовое поле изменится и свойство user).
onUserChange(){ this.$emit('userchange', this.userName); }
Первый параметр метода this.$emit()
должен представлять название события. В качестве последующих параметров мы можем передать произвольное
количество данных - в данном случае только обновленное имя пользователя.
Чтобы отловить это событие в объекте Vue на дочернем компоненте определен атрибут v-on:userchange
:
<useredit :user="name" v-on:userchange="change"></useredit>
То есть поскольку в дочернем компоненте генерируется событие userchange, то соответственно здесь и атрибут имеет определение v-on:userchange
.
Этому событию сопоставлен метод change:
change(value){ this.name = value; }
Параметр value представляет то значение, которое передается в дочернем компоненте через вызов this.$emit('userchange', this.userName);
,
то есть this.userName.
В итоге при вводе данных в дочернем компоненте useredit сработает обработчик события input - метод onUserChange, который сгенерирует событие namechange, которое в свою очередь будет обработано в родительском объекте в методе change.