Photo by Jonas Elia on Unsplash

เขียน Vue.js จะทำให้กดตรงนี้แล้ว ไปมีผลตรงนั้นยังไง !?! มาลองใช้ Event Bus กัน

Max Veerapat Kumchom
Grean Developers Family
3 min readMay 30, 2019

--

สวัสดีครับผมแมกซ์นะครับ หายไปอย่างนานเลย บ้านเมืองก็ยังไม่ไปไหน เฮ้อออ… สักบทความละกันนะครับ วันนี้คลายเครียดสักหน่อยหลังจากไม่ได้เขียนโคตรนาน ยังกะเลิกไปเลย ก็หายจริงแหละ ไม่ได้เข้ามาอ่านด้วย แต่วันนี้มาแล้วจ้า 🦈

ก่อนที่จะคุยกันเรื่อง Event Bus ที่จะมาแชร์กันในวันนี้ ! เริ่มคุยก่อนไป ว่าบทความนี้อาจจะไม่ละเอียดมากสักเท่าไหร่ คนที่เริ่มจากศูนย์อาจจะสับสน คนที่เขียน Vue.js มาสักพักก็คงเห็นเป็นเรื่องที่รู้ๆกันอยู่ เอาเป็นว่าจะมา เขียนเพื่อแชร์ละกัน เพราะสิ่งนี้เป็นสิ่งแรกๆ ที่ผมทำความเข้าใจ ตอนที่ผมเริ่มเขียน Vue.js และมันเป็นประโยชน์จริง จะพยายามเขียนให้ อ่านแล้วคุ้มกะเวลาที่เสียไปครับ ถ้าไม่ได้อะไรก็ขออภัยไว้ก่อน 🐶

เริ่ม ! ก่อนจะเริ่มเขียนเว็บด้วย Framework ต่างๆอย่าง Vue.js ก่อนอื่นเลยเนี้ย ต้องรู้จัก Component ก่อนเลย โดยการมองหน้าเว็บแบ่งเป็นส่วนประกอบต่างๆ ใหญ่เล็กว่ากันไป อะไรควรเป็นแม่ อะไรเป็นลูก โดยแม่มีลูกได้หลายๆคน สิ่งเหล่านี้ถูกแบ่งเป็น Parent Component, Child Component รายละเอียดจะข้ามไปนะ 😴

https://vuejs.org/v2/guide/components.html

หลังจากที่ผมเข้าใจสิ่งเหล่านี้ ต่อมาเมื่อเราเริ่มที่จะเขียนเลย ถ้าเราเริ่มด้วยการเขียนทุกอย่างในหน้าเดียว ทุกคนคุยกันได้สบายใจ ผ่านตัวแปรภายใน Component แต่เมื่อมาทำการแตกส่วนต่างๆเป็น Component ย่อยๆ เพื่อให้ง่ายต่อการนำมาใช้ใหม่ ซึ่งเป็นหลักการที่ควรทำ ทำให้เกิด Parent และ Child Component ขึ้น โดยการซ้อนทับกันเป็นชั้น ความลึกอยู่ที่การออกแบบ แต่ Component ยังต้องสื่อสารกันอยู่ 🤔

Component Communication การสื่อสารระหว่าง Component แปลตรงตัวเลย โดย Vue.js มีรูปแบบการสื่อสารกันหลายรูปแบบ

  • Props เป็นการสื่อสารแบบบนลงล่างคือ Parent > Child
  • Events เป็นการสื่อสารแบบล่างขึ้นบนคือ Child > Parent
  • Event Bus เข้าเรื่องแล้ว! เป็นการสื่อสารแบบ Publish/Subscribe
https://github.com/greenrobot/EventBus

คือสามารถที่จะทำการส่ง Event เข้าไปใน Event Bus เรียกว่า Publish แล้วจากนั้นสำหรับใครที่กำลัง Subscribe อยู่ ก็จะได้รับ Event นั้นไป การใช้ Event Bus บน Vue.js นั้นจึงทำให้เราสามารถที่จะทำให้ Component ใดๆ ที่ไม่ได้มีความสัมพันธ์กันเลย ยกตัวอย่าง เป็น Child ที่อยู่คนละ Parent ก็สามารถคุยกันได้ 🤩

ไม่เห็นจะต้องใช้เลยใช้ Props/Events ปกติก็ทำได้ ใช่ครับได้ แต่ถ้า Child ซ้อนลงไป 3 ชั้นนี่จะต้องส่ง Props ลงไปทุกๆชั้นเลยใช่ไหม Event Bus เข้ามาช่วยให้เรื่องพวกนี้ง่ายขึ้นนั้นเอง แต่ก็ไม่ใช่ จะใช้มันทุกครั้งไปนะครับ ไม่ Ok 🤣

โดยหลักการแล้ว การสร้าง Event Bus นั้น ใช้ความสามารถที่ Vue.js มีอยู่แล้วซึ่งก็คือ Events นั้นแหละแต่เรานำมาใช้ในระดับ Global นั้นเอง 😙 ต่อจากนี้จะเป็นการสร้างและใช้งานมันนะครับ

  • การสร้างแบบ new Vue(); โดยทำการสร้าง Vue Instance ขึ้นมาใหม่เลย ทำหน้าที่เฉพาะคือเป็น Event Bus อย่างเดียว คอยรับส่ง Event เท่านั้น

event-bus.js เป็นไฟล์ที่จะถูก import ใน Component ที่ต้องการใช้

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

ถ้าไม่อยากแยกไฟล์ก็ใช้ท่าใส่เข้าไปใน prototype ได้เลย

Vue.prototype.$EventBus = new Vue();const EventBus = this.$EventBus;
  • การสร้างแบบไม่ new Vue(); อ้าวแล้วไม่สร้างอะไรเลย มันจะมี Event Bus ไว้ใช้งานได้อย่างไร อย่าลืมไป App ของเราก็คือ Vue Instance ตัวหนึ่ง เราจะใช้มันนิแหละเป็น Event Bus โดยการเรียกหามันโดยใช้วิธีนี้🐻
const EventBus = this.$root;
Photo by Matthew T Rader on Unsplash

จะทำให้กดตรงนี้แล้ว ฝั่งผู้ส่งต้องทำการ Publish Event นั่นเองใน Vue.js เรียกว่า $emit โดยสามารถเรียกผ่าน Event Bus

  • การใช้งาน $emit ส่ง Event จะประกอบด้วย Event เป็น String บอกชื่อ Event ที่เราต้องการ Publish
EventBus.$emit('my-event-name');
  • การแนบค่าไปกับ Event ก็สามารถทำได้ โดยเพิ่มพารามิเตอร์ถัดไป ค่าก็จะถูกโยนไปใน Event Bus ด้วยโดยฝั่งรับก็จะต้องเขียนฟังชั่นก์ รับค่าเหล่านั้นด้วย
EventBus.$emit('my-event-name', param1, param2);

ไปมีผลตรงนั้นยังไง ฝั่งผู้รับต้องทำการ Subscribe Event ไว้ด้วยชื่อ เพื่อจะคอยรับเมื่อมีใคร $emit มายัง Event Bus ใน Vue.js เรียกว่า $on และ $off โดยสามารถเรียกผ่าน Event Bus เช่นกัน

  • การใช้งาน $on คอยรอรับฟัง Event นั้นประกอบด้วยชื่อ Event เป็น String ที่ต้องการจะ Subscribe ตามด้วยฟังชั่นก์ที่จะมาทำงานหลังจากได้รับ Event โดยถ้ามีพารามิเตอร์มาด้วย ฟังชั่นก์เหล่านั้นก็ต้องเขียนรอรับด้วย🌱
EventBus.$on('my-event-name', (param1, param2) => {   
console.log('Receive event.', param1, param2);
});
EventBus.$on('my-event-name', this.myHandlerFunction);

โดยการใช้ EventBus.$on จะนิยมนำไปไว้ในส่วนของ created(), mounted() ตามความเหมาะสมของ การทำงานของฟังชั่นก์

  • การใช้งาน $off เลิกรับฟัง Event คล้ายการ $on เป็นสิ่งสำคัญที่ห้ามลืมทำ เพราะหลังจาก Component นั้นไม่อยู่แล้วเราก็ควร Unsubscribe มันทิ้งไปด้วย
EventBus.$off('my-event-name');

โดยการใช้ EventBus.$off จะนิยมนำไว้ในส่วนของ beforeDestroy() เพื่อให้เมื่อ Component นั้นถูกทำลาย ให้ทำการ Unsubscribe ไปด้วย

  • แถมการใช้ $on, $off แบบ Registering Hooks Dynamically เป็นตัวช่วยให้เราจัดการ 🎄
export default {
mounted() {
EventBus.$on('my-event-name', (param1, param2) => {
console.log('Receive event.', param1, param2);
});
this.$on('hook:beforeDestroy', () => {
EventBus.$off('my-event-name');
});
}
};

จบไปแล้วนะครับกับ Event Bus ไม่ได้โค้ดให้ดูเลย แต่สำหรับใครยังไม่เคยใช ้อยากให้ลองดูนะครับ แต่ความจริงแล้วยังมีทางเลือกซึ่งเป็นอีกทางที่ดีเลย ก็จะเป็น Vuex ที่เป็น State management ไว้เจอกันครั้งหน้าลาหล่ะครับ 🤗

--

--