# 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, но ее мы с вами разберем позже.

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

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Сергей Китченков
5 дней назад
Здравствуйте! Спасибо за Ваш труд, все очень лаконично и понятно!
monsterlessons
5 дней назад
Добрый день. На здоровье)
danmer
19 дней назад
дратути, у меня не получается почему-то в колбэке присвоить новое значение this.text. хотя eventBus точно работает, текст выводится в консоли. мне кажется это всё из-за шаблона который я использую - vue-webpack-boilerplate. такое может быть?
monsterlessons
19 дней назад
Так сложно сказать. Надо дебажить.
danmer
19 дней назад
плохо(
danmer
18 дней назад
заработало, проблема была в том что эмит начинался раньше чем появлялся слушатель. и когда он слушал уже ничего не передавалось
monsterlessons
18 дней назад
Хорошо, что сами разобрались.
Virtualbox
1 месяц назад назад
Супер обучение, жду продолжения.
monsterlessons
1 месяц назад назад
На здоровье) Все будет.
Moe Green
1 месяц назад назад
Все четко )
monsterlessons
1 месяц назад назад
На здоровье)