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

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

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