Event Bus trong VueJS – Ngon mà lại không nên dùng?

0
Dịch vụ dạy kèm gia sư lập trình

Trong bài viết chia sẻ cách truyền dữ liệu giữa các compoent trong VueJS, trong đó có một trường hợp bạn cần phải truyền dữ liệu qua lại giữa nhiều component không cùng cấp.

Có nhiều cách để giải quyết vấn đề này, có thể dùng Vuex store hoặc sử dụng Event Bus. Hiểu nôm na, từ component cần truyền dữ liệu sẽ “bắn” một event kèm data lên Vue, component nào đã đăng ký nhận event đó sẽ nhận được và lấy dữ liệu ra dùng.

event bus trong vuejs

Với cách sử dụng event bus trong vuejs, bạn sẽ không còn quan tâm tới chuyện component cha con gì nữa hết, tất cả đều bình đẳng 😊 .

Qua bài viết này, mình sẽ hướng dẫn các bạn cách sử dụng Event Bus trong VueJS đơn giản nhất có thể nhé!

Khởi tạo Event Bus

Để mã nguồn được “thon gọn”, chúng ta nên tạo một file riêng để khởi tạo, đặt tên là EventBus.js

import Vue from 'vue'
const EventBus = new Vue()
export default EventBus

Bản chất Event Bus là một instance của Vue chứ không phải là một module hay thư viện tách rời, nó kế thừa các hàm có sẵn trong Vue.

Rất đơn giản phải không?

Sau khi đã khai báo xong, chúng ta sẽ xem cách gửi event như nào nhé!

Sending Event

Để gửi được event, đầu tiên là bạn cần phải import file đã khai báo ở trên. Sau đó, chỗ nào cần gửi event thì gọi hàm theo cú pháp sau: EventBus.$emit(<tên event>,<dữ liệu>);

Giả sử, mình có một màn hình với một nút nhấn và một input để nhập liệu. Khi người dùng nhấn vào đó, mình sẽ gửi event với nội dung mà người dùng vừa nhập. Ví dụ, mình muốn gửi dòng chữ:  “Xin chào các bạn độc giả VNTALKING”.

Giờ cứ gửi đã, còn ai nhận thì nhận 😊

// EventSend.vue
<template>
  <div id="sender-app">
    <div>
        <h2>Sender</h2>
        <el-input placeholder="Điền nội dung muốn gửi" v-model="text"></el-input>
        <el-button @click="sender">Send Event</el-button>
    </div>
  </div>
</template>

<script>
import EventBus from '../EventBus'; 
export default {
    name: 'sender-app',
    methods: {
        sender() {
            EventBus.$emit('message', this.text);
        }
    }
}
</script>

Listening Event

“Có người nói thì phải có người nghe”, à nhầm! Có component gửi event rồi thì cũng phải có component đăng ký lắng nghe nhận event đó.

Tại một component bất kỳ mà muốn nhận dữ liệu, bạn vẫn phải import file EventBus khai báo ở trên. Thay vì sử dụng hàm $emit(), bạn sẽ gọi hàm $on() để nhận dữ liệu.

// EventReceive.vue
import EventBus from '../EventBus'; 
export default {
    name: 'receiver-app',
    data () {
        return {
            list: []
        }
    },
    created() {
        EventBus.$on('message', text => this.list.push(text));
    },
}

Để tránh bị lỗi memory leak, bạn nên hủy lắng nghe khi component bị destroy.

Vậy là xong rồi đấy. Chạy thử ứng dụng và trải nghiệm nhé.

vuejs-eventbus-demo

 

Bạn có thể tải mã nguồn đầy đủ tại đây về tham khảo nhé.

Event Bus rất dễ sử dụng, và cũng hữu ích phải không? Mặc dù là bài viết tâng bốc Event Bus nhưng mình vẫn phải “kìm nén nỗi lòng” để khuyên bạn là “bạn không nên sử dụng Event Bus trong một số trường hợp”. Tại sao lại vậy?

💥 Đọc thêm các bài viết về VueJS

Tại sao không nên sử dụng Event Bus?

Vấn đề đầu tiên đó chính việc quản lý tên của event. Trong event bus, không có cơ chế nào để ngăn chặn việc trùng tên cả. Nên khi bạn vô tình hay cố ý để tên trùng nhau sẽ dẫn tới việc bên nhận sẽ không phân biệt cái nào cần nhận, cái nào không?

Cơ bản là phía vue không có cơ chế quản lý, mọi việc sẽ đổ hết lên đầu ông DEV. Gặp bạn dev nào cẩn thận thì còn đỡ, gặp ông nào cẩu thả thì xác định dự án của bạn sẽ rất nát 😞

Vấn đề thứ hai đó chính phải cẩn thận trong việc hủy đăng ký lắng nghe event. Nếu không hủy, ngay khi component đã bị destroy, event bus vẫn tiếp tục lắng nghe. Nhẹ thì ứng dụng chạy không đúng như thiết kế, nặng thì có thể bị memory leak.

Vấn đề cuối cùng đó là rất khó debug. Chính hàm $on() dùng để lắng nghe sự kiện và nhận data rất khó trace ngược lại code. Khi có lỗi xảy ra, bạn không biết trace code kiểu gì, không biết thằng nào đang gửi event đó.

Vậy phải làm thế nào?

Lời khuyên của mình đó là Vuex Store để thay thế. Chúng ta sẽ gửi dữ liệu lên store chung. Nhờ cơ chế reactive mà các component khác cũng sẽ tự động cập nhật khi store thay đổi dữ liệu.

Cụ thể cách sử dụng Vuex như nào, các bạn đọc lại bài viết này nhé: Sử dụng thư viện Vuex để quản lý State trong VueJS

Cám ơn các bạn đã đọc bài và hẹn gặp lại ở bài viết tới nhé!

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trướcCách định dạng tiền tệ trong javascript (3 cách)
Bài tiếp theo[Design Pattern] Một ví dụ ứng dụng Strategy Pattern trong thực tế
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo