หัดเขียน Vue.js เล่นๆ EP.2
Life Cycle Hook ใน Vue.js
ตอนอื่นๆใน Series นี้
ตอนที่ 1 เริ่มต้นทำความรู้จักกับ Vue.js
ตอนที่ 2 Life Cycle Hook ใน Vue.js
สวัสดีครับ ต่อจากบทความที่แล้วนะครับ ในบทความนี้จะมาพูดถึง Life Cycle ที่มีอยู่ใน Vue.js กันครับ
Life Cycle คืออะไร ?
Life cycle คือเหตุการณ์ หรือ วัฏจักรของ Vue instance เริ่มตั้งแต่ ถูกสร้างขึ้น จนถึง ถูกทำลายไป ซึ่งตรงนี้แหละ ที่เราสามารถ Hook เข้าไปเพื่อทำอะไรบางอย่าง ในแต่ละเหตุการณ์ได้
จาก diagram ข้างบน จัดเรียงตามเหตุการณ์ได้ดังนี้
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destoryed
beforeCreate
เหตุการนี้จะเกิดขึ้นก่อนที่ Component จะถูก render เข้าไปใน DOM และเกิดก่อนเหตุการณ์ทั้งหมด ในขั้นตอนนี้ เราสามารถที่จะดักจับเหตุการณ์ ก่อนที่จะเกิดเหตุการณ์อื่นๆได้
ลองสังเกตจากโค้ดชุดนี้ดูครับ
จากโค้ดนี้ เราได้ทำการ ประกาศตัวแปรชื่อ name และกำหนดว่าเป็น ‘john’ ไว้
จากนั้นทำการ log ดูค่าตัวแปร ตั้งแต่ beforeCreate ไปจนถึง beforeMount
ลองรันเพื่อดูผลลัพธ์
จะเห็นว่า ถึงแม้ว่า ทั้ง 3 เหตุการณ์นี้ ข้อมูลจะยังไม่ถูก Mount เข้าไปใน DOM แต่เราก็ยังสามารถดึงค่าที่ประกาศไว้ มาใช้ได้อยู่ ยกเว้น! beforeCreate เหตุผลเป็นเพราะว่า beforeCreate เกิดก่อนการสร้าง Component หรือการประกาศตัวแปร นั่นเอง
โอเค แล้วถ้าเราเขียนแบบนี้ละ
ผลลัพธ์ที่ได้จะเป็นแบบนี้
เหตุที่เป็นแบบนี้ ก็เพราะว่า เราใช้ beforeCreate Hook เข้าไปแก้ DOM โดยตรง จากคำว่า {{ firstName }} ให้เป็นคำว่า {{ lastName }} พอเวลามัน Mount ข้อมูลเข้าไปยัง DOM ปกติ ที่เป็น {{ firstName }} เลยกลายเป็น {{ lastName }} แทน เลยทำให้แสดงคำว่า bunsaen แทนที่จะเป็น pasupol นั่นเองครับ
created
ในเหตุการณ์นี้ ทุกอย่างจะถูกเตรียมไว้ครบหมดแล้ว และสามารถ เข้าถึงได้หมด ไม่ว่าจะเป็น Methods, Object, หรือ ตัวแปร ที่ได้ประกาศไว้ เป็นต้น
ซึ่งทำให้เราสามารถดึงตัวแปร และ Methods ที่ประกาศไว้ มาแสดงได้
beforeMount
ในเหตุการณ์นี้ จะทำการ Compile Template และนำไป Update ใน Visual DOM พร้อมทั้งเพิ่มเข้าไปใน Vue Instance ที่เหลือก็แค่เตรียม สร้าง Elements และ Mount เข้าไปยัง Native DOM จริงๆ
beforeMount() {
console.log('DOM ยังไม่ถูกสร้าง แต่จะมาในเร็วๆนี้');
}
mounted
ในเหตุการณ์นี้ จะเกิดขึ้นเมื่อ DOM ถูกสร้างเสร็จแล้ว เราสามารถ เข้าถึง Element ต่างๆใน DOM ได้ทั้งหมด เช่นการ ดึงข้อมูลจาก input เป็นต้น เช่น
จากโค้ดด้านบนนี้ คิดว่า ถ้ารันแล้วจะเกิดอะไรขึ้น ?
พัง! ครับ ที่เป็นแบบนี้ก็เพราะว่า ในโค้ดเรา ได้ทำการ log ดูข้อมูลจาก input box ใน beforeMount ซึ่งตอนนี้ Component ยังไม่ได้ถูก Mount เข้าไปใน DOM นั่นเองครับ พอมันไม่เจอ Element ก็เลยทำให้เกิด Error แต่หลังจาก Mount เสร็จแล้ว ค่อยเรียก ใน mounted ก็จะสามารถเข้าถึง input และดึง value ออกมาได้ตามปกติ
beforeUpdate
เหตุการณ์นี้ เกิดขึ้นก่อนที่จะมีการ Update ข้อมูลต่างๆใน DOM คือในระหว่างที่ จะทำการ Update DOM เราสามารถใช้ช่วงระยะเวลานี้ เปลี่ยนแปลงบางอย่าง จากนั้นค่อยทำการ Update ข้อมูลใหม่เข้าไปใน DOM ครับ อาจจะงงๆ เรามาดูโค้ดนี้กันครับ
ในโค้ดนี้เราได้กำหนดว่า ถ้ามีการกดปุ่ม จะไปเรียกฟังก์ชั่น showName() ให้ทำงาน ซึ่งจะกำหนดให้ตัวแปร name จากค่าว่าง เป็นคำว่า ‘john’ (ตัวพิมพ์เล็ก)
แต่ในขณะเดียวกัน ก่อนที่ข้อมูลนั้นจะถูก Update เราได้ใช้ beforeUpdate ดักจับเหตุการณ์เพื่อเปลี่ยนคำว่า ‘john’ (ตัวพิมพ์เล็ก) ให้ไปเป็น ‘JOHN’ ตัวพิมพ์ใหญ่ แทน
ผลลัพธ์ที่ได้
updated
เหตุการณ์นี้ จะเกิดหลังการ re-renders หรือ การ Update ตัว Elements ใน DOM ตัวอย่างเช่น
จากโค้ดด้านบน เราได้ทำการสร้าง ฟังก์ชั่น counter ขึ้นมา แล้วให้ เพิ่มจำนวนขึ้นไปหนึ่งค่า ในทุกๆครั้งที่มีการกดปุ่ม แล้วใน updated hook ก็ได้ทำการ log เพื่อดูผลลัพธ์
จากผลลัพธ์ที่ได้ แสดงให้เห็นว่า ในทุกๆครั้งที่มีการกดปุ่ม และ Elements ใน DOM มีการเปลี่ยนแปลง จะทำให้ updated hook ทำงาน
beforeDestroy
เหตุการณ์นี้จะเกิดขึ้นก่อนที่ Vue Instance จะถูกทำลาย หรือก่อนที่ Event ต่างๆจะหยุดการทำงาน ตัวอย่างเช่น
จากโค้ดด้านบนนี้ เราได้ทำสร้าง timer ขึ้นมา ซึ่งจะเพิ่มจำนวนขึ้นไปเรื่อยๆ ทีละหนึ่ง ในทุกๆหนึ่งวินาที
จากนั้นเราได้ทำการสร้าง Methods สำหรับหยุด timer ขึ้นมา (stopTimer) ซึ่งเมื่อทำการคลิกที่ปุ่ม stop timer จะทำให้ Vue Instance นั่นถูก $destroy หรือหยุดการทำงาน
จากนั้นก่อนที่ Vue Instance จะถูกทำลาย เราได้ใช้ beforeDestroy hook เข้าไปเพื่อบันทึกค่าล่าสุดของ time ลงไปใน localStorage
ลองมาดูผลลัพธ์กันครับ
destroyed
มาถึงเหตุการณ์สุดท้ายแล้วนะครับ ขนาด ชีวิตของคนเรา ยังมี เกิด แก้ เจ็บ ตาย เป็นธรรมดา ใน Components ก็เช่นกันครับ สำหรับ destroyed จะเกิดขึ้นหลังจาก Event ต่างๆถูกทำลาย หรือ หยุดลง ซึ่งจะทำให้เราไม่สามารถเข้าถึง Elements หรือ Event ต่างๆ ที่ถูกสร้างจาก Vue Instance ได้ แต่ถึงกระนั้น เราก็ยังสามารถเข้าถึงตัวแปร ต่างๆที่เคยประกาศไว้ได้ สังเกตุได้จากโค้ดชุดนี้ครับ
ต่อจากอันที่แล้ว (beforeDestroy) ในโค้ดนี้ เราได้ทำการ log ดูข้อมูล จาก ตัวแปร time และ พยายาม เข้าถึง Elements โดยการใช้ ref หลังจาก Vue Instance ถูกทำลาย (destroyed) ลงไปแล้ว
ผลลัพธ์ที่ได้คือ
จะเห็นได้ว่า หลังจากที่เรากดปุ่ม stop timer แล้วสั่งให้ Vue Instance $destroy ไปเราจะไม่สามารถ ใช้คำสั่ง ref เพื่อ อ้างถึง หรือ เข้าถึง Elements นั้นได้เลย แต่เราก็ยังสามารถ เข้าถึงตัวแปร นั่นๆได้ ถึงแม้ Vue Instance จะถูกทำลายลงไป