Главная » Статьи » Использование Event Bus для обмена свойствами между компонентами Vue

Использование Event Bus для обмена свойствами между компонентами Vue

Использование Event Bus для обмена свойствами между компонентами Vue

От автора: для чего можно использовать в Vue Event Bus? По умолчанию связь между компонентами Vue происходит с использованием свойств. Эти свойства передаются из родительского компонента в дочерний.

Например, вот компонент, в котором title является свойством:

<blog-post title="My journey with Vue"></blog-post>

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

Таким образом, сквозная передача может быть одной из потенциальных проблем. Другая — взаимодействие между несвязанными компонентами. Мы можем решить все это, используя Event Bus.

Что такое Event Bus? Ну, это в основном раскрыто в самом названии. Это способ транспортировки для компонента с целью передачи свойства от одного компонента другому — независимо от того, где эти компоненты расположены в дереве.

Практическая задача: создание счетчика

Давайте рассмотрим реальный пример, чтобы продемонстрировать концепцию Event Bus. Счетчик, который добавляет или вычитает предоставленное значение и подсчитывает общую сумму, является подходящим для рассмотрения случаем:

Чтобы использовать Event Bus, сначала необходимо инициализировать его:

import Vue from 'vue';
const eventBus = new Vue();

Это задает экземпляр Vue для eventBus. Вы можете назвать его, как угодно. Если вы используете однофайловый компонент, то у вас должен быть сниппет в отдельном файле, так как вам в любом случае придется экспортировать экземпляр Vue, назначенный как eventBus:

import Vue from 'vue';
export const eventBus = new Vue();

После этого мы можем начать использовать его в компоненте счетчика. Вот что мы хотим сделать:

Мы хотим получить счетчик с начальным значением 0.

Мы хотим добавить поле ввода, которое принимает числовые значения.

Нам нужны две кнопки: одна при нажатии будет добавлять переданное числовое значение, а другая — вычитать указанное числовое значение.

Мы хотим получать подтверждение того, что произошло, когда сумма изменится.

Так выглядит шаблон с каждым из этих элементов:

<div id="app"> <h2>Counter</h2> <h2>{{ count }}</h2> <input type="number" v-model="entry" /> <div class="div__buttons"> <button class="incrementButton" @click.prevent="handleIncrement"> Increment </button> <button class="decrementButton" @click.prevent="handleDecrement"> Decrement </button> </div> <p>{{ text }}</p>
</div>

Мы привязываем поле ввода к значению, называемому entry, которое мы будем использовать для увеличения или уменьшения суммы, в зависимости от того, что выбрал пользователь. Когда нажата любая кнопка, мы запускаем метод, который должен либо увеличивать, либо уменьшать значение счетчика. Наконец, {{text}}, содержащееся в теге <p>, является сообщением, которое мы выводим, оно подытоживает внесенные изменения. Вот как все это происходит в нашем скрипте:

new Vue({ el: '#app', data() { return { count: 0, text: '', entry: 0 } }, created() { eventBus.$on('count-incremented', () => { this.text = `Count was increased` setTimeout(() => { this.text = ''; }, 3000); }) eventBus.$on('count-decremented', () => { this.text = `Count was decreased` setTimeout(() => { this.text = ''; }, 3000); }) }, methods: { handleIncrement() { this.count += parseInt(this.entry, 10); eventBus.$emit('count-incremented') this.entry = 0; }, handleDecrement() { this.count -= parseInt(this.entry, 10); eventBus.$emit('count-decremented') this.entry = 0; } }
})

Возможно, просмотрев этот код, вы заметили, как мы собираемся использовать Event Bus.

Первое, что нам нужно сделать, это установить путь для отправки события от одного компонента к другому. Мы можем проложить этот путь с помощью eventBus.$Emit() (при этом emit является причудливым словом для обозначения отправки). Эта передача включена в два метода: handleIncrement и handleDecrement, которые прослушивают ввод данных. И, как только это произойдет, наш автобус событий отправляется к любому компоненту, который запрашивает данные, и перевозит свойство.

Возможно, вы заметили, что с помощью eventBus.$on() мы прослушиваем оба события в хуке жизненного цикла created(). В обоих случаях мы должны передать строку, соответствующую событию, которое мы запустили. Это похоже на идентификатор для конкретного события, вся суть заключается в том, чтобы установить способ получения данных компонента. Когда eventBus распознает определенное событие, которое было объявлено, вызывается следующая функция: мы устанавливаем текст для отображения того, что произошло, и скрываем его через три секунды.

Практическая задача: обработка нескольких компонентов

Предположим, мы работаем над страницей профиля, где пользователи могут обновлять свое имя и адрес электронной почты для приложения, а затем просматривать обновления без перезагрузки страницы. Это можно просто сделать с использованием Event Bus, хотя на этот раз мы имеем дело с двумя компонентами: профилем пользователя и формой, через которую предоставляются изменения профиля.

Вот шаблон:

<div class="container"> <div id="profile"> <h2>Profile</h2> <div> <p>Name: {{name}}</p> <p>Email: {{ email }}</p> </div> </div> <div id="edit__profile"> <h2>Enter your details below:</h2> <form @submit.prevent="handleSubmit"> <div class="form-field"> <label>Name:</label> <input type="text" v-model="user.name" /> </div> <div class="form-field"> <label>Email:</label> <input type="text" v-model="user.email" /> </div> <button>Submit</button> </form> </div>
</div>

Мы передадим идентификаторы (user.name и user.email) соответствующему компоненту. Во-первых, давайте настроим шаблон для компонента Edit Profile (edit__profile), содержащего данные имени и электронной почты, которые мы хотим передать, в компонент Profile, который мы будем устанавливать дальше. Опять же, мы создали Event Bus, чтобы передавать эти данные после того, как он обнаружил, что произошло событие ввода данных.

new Vue({ el: "#edit__profile", data() { return { user: { name: '', email: '' } } }, methods: { handleSubmit() { eventHub.$emit('form-submitted', this.user) this.user = {} } }
})

Эти данные будут использоваться для интерактивного обновления профиля пользователя в компоненте Profile (profile), который ожидает передачи name и email, когда автобус прибывает на его хаб.

new Vue({ el: '#profile', data() { return { name: '', email: '' } }, created() { eventHub.$on('form-submitted', ({ name, email}) => { this.name = name; this.email = email }) }
})

Их вещи упакованы. Теперь все, что им нужно сделать, это отправиться домой. Довольно круто, не так ли? Несмотря на то, что компоненты Edit Profile и Profile не связаны друг с другом (или не связаны прямыми взаимоотношениями родитель-потомок), они могут общаться друг с другом, связанные одним и тем же событием.

Заключение

Я нашел Event Bus полезным в случаях, когда мне нужно включить в приложение реактивность, а именно, обновить компонент на основе ответа, полученного с сервера, не обновляя страницу. Также возможно, чтобы запускаемое событие прослушивалось более чем одним компонентом. Если у вас есть другие интересные сценарии использования Event Bus, я буду рад услышать о них в комментариях.

Автор: Kingsley Silas

Источник: https://css-tricks.com/

Редакция: Команда webformyself.