เนื้อหาตอนที่แล้วเราได้รู้จักกับการสร้าง reactive state ด้วย reactive
ฟังก์ชั่น รวมถึงได้รู้จักข้อจำกัดและแนวทางการเลือกใช้งานระหว่างฟังก์ชั่น ref()
และฟังก์ชั่น reactive() เนื้อหานี้เรามาดูต่อเกี่ยวกับอีกรูปแบบของกรสร้างหรือ
กำหนดตัวแปรสำหรับ reactive state ด้วยฟังก์ชั่น computed()
การใช้งาน computed() ฟังก์ชัน
โดยปกติเราสามารถใช้ expression สำหรับกำหนดรูปแบบการแสดงข้อมูลใน template
ได้อย่างสะดวกและง่ายอยู่แล้ว แต่กับรูปแบบการจัดการที่ซับซ้อน การกำหนด expression
ที่มีความซับซ้อนหรือยาวหรือมีเงื่อนไข logic ที่ค่อนข้าง ก็จะทำให้ template นั้นจะดูรก
และก็จัดการยากขึ้น
ดูรูปแบบการใช้งาน expression ที่เริ่มมีความซับซ้อนขึ้น
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | < script setup> import { ref, reactive, computed } from 'vue' const count = ref(0) function increment() { count.value++ } const author = reactive({ name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] }) </ script > < template > < button @ click = "increment" > {{ count }} </ button > < br > < p >Has published books:</ p > < span >{{ author.books.length > 0 ? 'Yes' : 'No' }}</ span > </ template > |
สังเกตส่วนนี้
1 | < span >{{ author.books.length > 0 ? 'Yes' : 'No' }}</ span > |
ถ้าจำนวนหนังสือของผู้แต่งมีมากกว่า 2 ก็แสดงว่าผู้แต่งนี้มีหนังสือตีพิมพ์ ให้ค่าเป็น yes
จะเห็นว่าเราสามารถใช้ expression ในรูปแบบนี้เพื่อแสดงผลได้ แต่ถ้าจะดีกว่านี้ ถ้าเรา
ใช้เครื่องมือที่เป็นฟังก์ชั่น computed() สำหรับช่วยในการคำนวณและแสดงผลข้อมูลโดย
อัตโนมัติ โดยคำนวณค่าจากข้อมูลอื่น ๆ ใน Vue instance หรือ component โดยไม่
ต้องเปลี่ยนแปลงข้อมูลต้นฉบับโดยตรง และจะถูกอัปเดตโดยอัตโนมัติเมื่อข้อมูลต้นฉบับเปลี่ยนแปลง
แถมยังทำให้การเขียนโค้ดดูสะอาดตามากขึ้น โดยสามารถเขียนได้เป็นดังนี้
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | < script setup> import { ref, reactive, computed } from 'vue' const count = ref(0) function increment() { count.value++ } const author = reactive({ name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] }) // a computed ref const publishedBooksMessage = computed(() => { return author.books.length > 0 ? 'Yes' : 'No' }) </ script > < template > < button @ click = "increment" > {{ count }} </ button > < br > < p >Has published books:</ p > < span >{{ publishedBooksMessage }}</ span > </ template > |
publishedBooksMessage คือ computed property หรือ reactive state ที่
สร้างด้วยฟังก์ชั่น computed() ซึ่งจะได้ค่าผลลัพธ์ที่ได้จากคำนวณมาแสดงผลเหมือนๆ
กับ state ทั่วไป และข้อดีสำคัญก็คือมันสามารถใช้ผลลัพธ์ที่เป็นค่าแคช โดยไม่ทำงานตลอด
เวลา ถ้าข้อมูล state ที่เกี่ยวข้องไม่มีการเปลี่ยนแปลง ซึ่งต่างจาก ถ้าเราใช้เป็นฟังก์ชั่น ใน
ลักษณะดังนี้
รูปแบบการใช้งานแบบฟังก์ชั่น
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | < script setup> import { ref, reactive, computed } from 'vue' const count = ref(0) function increment() { count.value++ } const author = reactive({ name: 'John Doe', books: [ 'Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery' ] }) function publishedBooksMessage(){ return author.books.length > 0 ? 'Yes' : 'No' } </ script > < template > < button @ click = "increment" > {{ count }} </ button > < br > < p >Has published books:</ p > < span >{{ publishedBooksMessage() }}</ span > </ template > |
การใช้งานในรูปบบฟังก์ชั่นข้างต้น ทุกครั้งที่ template มีการเรนเดอร์หรือโหลดใหม่ก็จะทำงาน
ฟังก์ชั่นทุกครั้ง ซึ่งในกรณีที่มีรูปแบบการทำงานที่ซับซ้อนมากๆ ก็จะส่งผลเสียต่อประสิทธิภาพการ
ทำงานของโปรแกรมโดยรวม ในขณะที่ถ้าเราใช้งานด้วยฟังก์ชั่น computed() จะทำงานก็เมื่อ
state ที่เกี่ยวข้องมีการเปลี่ยนแปลงค่าเท่านั้น หากยังเป็นค่าเดิม ก็จะใช้ค่าแคชก่อนหน้ามาแสดง
แทน ทำให้สามารถทำงานได้เร็วขึ้น
อย่างไรก็ดีข้อความระวังและหลีกเลี่ยงสำหรับการใช้งานฟังก์ชั่น computed เพื่อกำหนดค่า state
ควรใช้งานสำหรับคำนวณและแสดงผลลัพธ์เท่านั้น ไม่ควรใช้สำหรับปรับเปลี่ยนค่า state อื่นภายใน
ฟังก์ชั่น หรือห้ามใช้สำหรับการทำงานในรูปแบบ async หรือมีเวลาที่ต้องรอเข้ามาเกี่ยวข้อง รวมถึง
ห้ามใช้สำหรับแก้ไข DOM ภายในฟังก์ชั่นหรือการคำนวณดังกล่าว