Во Vue.js также можно организовать взаимодействие между компонентами, которые находятся на одном уровне, то есть являются сестринскими.
В этом случае взаимодействие происходит через родительский компонент. Например, определим два дочерних компонента, которые взаимодействуют через родительский компонент:
<!DOCTYPE html> <html> <head> <title>Компоненты Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <h2>User</h2> <useredit :name="user" @userchange="change"></useredit> <userinfo :name="user" @userreset="reset"></userinfo> </div> <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script> <script> Vue.component('useredit', { props: ["name"], template: '<div><input v-model="name" /><button @click="save">Save</button></div>', methods:{ save(){ this.$emit("userchange", this.name); } } }); Vue.component('userinfo', { props: ["name"], template: `<div><p>Имя: {{name}}</p><button @click="reset">Reset</button></div>`, methods:{ reset(){ this.$emit("userreset"); } } }); new Vue({ el: "#app", data:{ user:'Tom' }, methods:{ change(name){ this.user = name; }, reset(){ this.user = 'Tom'; }, } }); </script> </body> </html>
В данном случае оба дочерних компонента принимают от объекта Vue имя пользователя. То есть оба компонента используют те данные, которые определены в объекте Vue. Если один компонент хочет изменить эти данные, то он генерирует событие. Объект Vue обрабатывает это событие и изменяет данные. После этого данные автоматически изменяются во втором компоненте. То есть объект Vue здесь служит медиатором, а непосредственно между собой компоненты не взаимодействуют.
Еще один способ взаимодействия между компонентами одного уровня представлет применение шины событий. Ее суть заключается, в определении объекта Vue, который будет выполнять роль шины событий:
var eventBus = new Vue();
В компоненте, который хочет изменить данные, мы вызываем через эту шину событие:
eventBus.$emit("событие", данные);
А в другом компоненте в методе created устанавливаем обработчик этого события:
created(){ eventBus.$on("событие", (данные)=>{ // действия }); }
Например, рассмотрим следующий пример:
<!DOCTYPE html> <html> <head> <title>Компоненты Vue.js</title> <meta charset="utf-8" /> </head> <body> <div id="app"> <h2>User</h2> <useredit :user="user"></useredit> <userinfo :user="user"></userinfo> </div> <script src="https://unpkg.com/vue@2.7.14/dist/vue.js"></script> <script> var eventBus = new Vue(); Vue.component('useredit', { props: ["user"], template: `<div> <input v-model="userName" /> <button @click="save">Save</button> </div>`, data: function () { return { userName: this.user} }, methods:{ save(){ eventBus.$emit("userchange", this.userName); } } }); Vue.component('userinfo', { props: ["user"], template: '<div><p>Имя: {{userName}}</p></div>', data: function () { return { userName: this.user} }, created(){ eventBus.$on("userchange", (name)=>{ this.userName = name; }); } }); new Vue({ el: "#app", data:{ user:'Tom' } }); </script> </body> </html>
Здесь объект Vue не обрабатывает никаких событий и просто передает в компоненты имя пользователя. В самих компонентах привяка идет не к свойству из props, а к свойству из параметра data. То есть в данном случае даже если бы мы, как в предыдущем примере, захотели бы изменить значения свойств через обработку событий в объекте Vue, то мы бы не смогли бы это сделать. Однако благодаря шине событий мы все же это можем сделать. Компонент useredit вызывает через шину событий событие userchange, а второй компонент - userinfo обрабатывает это событие.