เนื้อหาตอนที่แล้วเราได้รู้จักกับการสร้าง reactive state ด้วย reactive
ฟังก์ชั่น รวมถึงได้รู้จักข้อจำกัดและแนวทางการเลือกใช้งานระหว่างฟังก์ชั่น ref()
และฟังก์ชั่น reactive() เนื้อหานี้เรามาดูต่อเกี่ยวกับอีกรูปแบบของกรสร้างหรือ
กำหนดตัวแปรสำหรับ reactive state ด้วยฟังก์ชั่น computed()
การใช้งาน computed() ฟังก์ชัน
โดยปกติเราสามารถใช้ expression สำหรับกำหนดรูปแบบการแสดงข้อมูลใน template
ได้อย่างสะดวกและง่ายอยู่แล้ว แต่กับรูปแบบการจัดการที่ซับซ้อน การกำหนด expression
ที่มีความซับซ้อนหรือยาวหรือมีเงื่อนไข logic ที่ค่อนข้าง ก็จะทำให้ template นั้นจะดูรก
และก็จัดการยากขึ้น
ดูรูปแบบการใช้งาน expression ที่เริ่มมีความซับซ้อนขึ้น
<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>
สังเกตส่วนนี้
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
ถ้าจำนวนหนังสือของผู้แต่งมีมากกว่า 2 ก็แสดงว่าผู้แต่งนี้มีหนังสือตีพิมพ์ ให้ค่าเป็น yes
จะเห็นว่าเราสามารถใช้ expression ในรูปแบบนี้เพื่อแสดงผลได้ แต่ถ้าจะดีกว่านี้ ถ้าเรา
ใช้เครื่องมือที่เป็นฟังก์ชั่น computed() สำหรับช่วยในการคำนวณและแสดงผลข้อมูลโดย
อัตโนมัติ โดยคำนวณค่าจากข้อมูลอื่น ๆ ใน Vue instance หรือ component โดยไม่
ต้องเปลี่ยนแปลงข้อมูลต้นฉบับโดยตรง และจะถูกอัปเดตโดยอัตโนมัติเมื่อข้อมูลต้นฉบับเปลี่ยนแปลง
แถมยังทำให้การเขียนโค้ดดูสะอาดตามากขึ้น โดยสามารถเขียนได้เป็นดังนี้
<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 ที่เกี่ยวข้องไม่มีการเปลี่ยนแปลง ซึ่งต่างจาก ถ้าเราใช้เป็นฟังก์ชั่น ใน
ลักษณะดังนี้
รูปแบบการใช้งานแบบฟังก์ชั่น
<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 ภายในฟังก์ชั่นหรือการคำนวณดังกล่าว