# Eventbus в Vue.js

06:24
poster
В этом видео мы разберем, как передавать данные между компонентами с помощью eventBus в Vue
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

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

В Vue есть встроенный publish subscribe паттерн, который позволяет нам передавать данные между любыми компонентами. Очень часто его еще называют event bus.

На данный момент у нас есть парент App компонент и 2 child компоненты LoginForm и SuccessMessage.

Давайте порефакторим эти компоненты, чтобы убрать необходимость передавать данные через parent.

Было бы замечательно, чтобы в любом компоненте мы могли импортировать eventBus в таком стиле

import {eventBus} from './main'

И чтобы eventBus уже содержал нужные методы для подписки и отправки евентов.

Для этого достаточно инициализировать новый экземпляр Vue, так как методы для publish subscribe лежат в руте инстанса Vue.

main.js

export const eventBus = new Vue()

new Vue({
  el: '#app',
  render: h => h(App)
})

Теперь мы можем импортировать eventBus в LoginForm, как я показывал ранее.

LoginForm.vue

import {eventBus} from './main'
...

Теперь нам достаточно изменить this.$emit на eventBus.$emit. Он будет работать абсолютно в таком же виде, но содержать всех подписчиков не в компоненте, а внутри обьекта eventBus. Именно поэтому нам не нужны другие компоненты для взаимодействия.

LoginForm.vue

eventBus.$emit('login', {
  email: this.email,
  password: this.password
})

Теперь мы хотим подписаться в компоненте SuccessMessage на событие login. Сначала мы должны импортировать eventBus, как мы делали с LoginForm.

SuccessMessage.vue

import {eventBus} from './main'

Теперь мы должны подписаться на евент login.

У каждого компонента есть специальный хук created, внутри которого мы можем написать какой-то код, и он сработает, когда этот компонент создастся.

Давайте попробуем добавить created в SuccessMessage.

SuccessMessage.vue

export default {
  ...
  created () {
    console.log('component was created')
  }
}

Если мы посмотрим в браузер, то у нас вывелось сообщение created. Теперь мы можем подписаться на наш евент login внутри него и тогда при создании компонента мы всегда будет подписываться на этот евент.

SuccessMessage.vue

data () {
  return {
    email: ''
  }
},
created () {
  eventBus.$on('login', data => {
    this.email = data.email
  })
}

Здесь мы использовали $on метод из eventBus. Первым аргументом мы передаем название евента, который мы хотим слушать, в нашем случае, это login. Вторым аргументом мы передаем callback, который произойдет, когда этот евент сработает. Первым параметром этот коллбека мы получаем данные, которые мы передали из LoginForm компонента. После чего мы просто обновляет локальную переменную email у компонента.

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

Подход с eventBus очень легкий в использовании, но может быть сложным в поддержке, когда у нас огромное количество евентов в приложении и каждый компонент может поменять самого себя слушая какой-то евент. Именно поэтому его нужно применять с осторожностью. Подход с передачей данных через parent компонент намного легче дебавижить, по сравнению с eventBus, но мы пишем больше кода.

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

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

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Дмитрий Г
2 месяцев назад
Отличное видео, спасибо!!! вопрос: в SuccessMessage.vue мы подписываемся на евент login с помощью специального хука created. Как можно написать код по другому в SuccessMessage.vue не используя хук created? К чему или на что подвесить созданное в LoginForm.vue событие login? Как его можно слушать? addEventListener(login, callback), это как в js. Вешать событие на темплате? v-on:login="callback". так?
monsterlessons
2 месяцев назад
В Vue используют либо EventBus, как я показал в этом видео, либо Vuex для того, чтобы триггерить события и слушать их. Подписка в хуке created - это стандартная практика. @login="callback" - я показывал в этом видео https://monsterlessons.com/project/lessons/peredaem-dannye-iz-child-v-parent-v-vue
Gemorroj
2 месяцев назад
получается для шины событий нужно создавать отдельный экземпляр Vue? нельзя ли использовать основой (https://github.com/monsterlessons/eventbus-in-vue/blob/master/src/main.js#L6)?
monsterlessons
2 месяцев назад
Мы делаем это, так как хотим создать pub sub, который абсолютно не привязан к нашему инстансу Vue. По факту они могли бы сделать что-то вроде import {eventBus} from 'vue'
Сергей Китченков
4 месяцев назад
Здравствуйте! Спасибо за Ваш труд, все очень лаконично и понятно!
monsterlessons
4 месяцев назад
Добрый день. На здоровье)
danmer
5 месяцев назад
дратути, у меня не получается почему-то в колбэке присвоить новое значение this.text. хотя eventBus точно работает, текст выводится в консоли. мне кажется это всё из-за шаблона который я использую - vue-webpack-boilerplate. такое может быть?
monsterlessons
5 месяцев назад
Так сложно сказать. Надо дебажить.
danmer
5 месяцев назад
плохо(
danmer
5 месяцев назад
заработало, проблема была в том что эмит начинался раньше чем появлялся слушатель. и когда он слушал уже ничего не передавалось
monsterlessons
5 месяцев назад
Хорошо, что сами разобрались.
Virtualbox
5 месяцев назад
Супер обучение, жду продолжения.
monsterlessons
5 месяцев назад
На здоровье) Все будет.
Moe Green
5 месяцев назад
Все четко )
monsterlessons
5 месяцев назад
На здоровье)