เนื้อหาตอนต่อไปนี้ เรามาดูพื้นฐานส่วนที่สำคัญอีกส่วนหนึ่ง นั่นก็คือ
เกี่ยวกับ Reactivity System และการกำหนดตัวแปร หรือใน vuejs
มักจะเรียกว่า Reactive State ซึ่งเราได้ผ่านตารูปแบบการใช้งานเบื้องต้น
มาแล้วบ้าง นั่นก็คือการกำหนดโดยใช้ฟังก์ชั่น ref()
เกี่ยวกับ Reactive State ใน vuejs
ใน Vue.js, Reactive State หมายถึงการที่ข้อมูลที่ถูกใช้ในแอพพลิเคชั่น Vue.js จะถูก
ติดตามการเปลี่ยนแปลงและอัพเดตอัตโนมัติเมื่อมีการเปลี่ยนแปลงข้อมูลนั้น ๆ โดยอัตโนมัติและ
อย่างรวดเร็ว การทำให้ข้อมูลเป็น Reactive เป็นสิ่งสำคัญที่ทำให้ Vue.js มีประสิทธิภาพและ
เป็นมาตรฐานสำหรับการพัฒนาแอพพลิเคชันที่ไหลไปมาของข้อมูลอย่างกระชับและเรียลไทม์
โดยไม่ต้องตรวจสอบเงื่อนไขเพื่ออัพเดตข้อมูลด้วยตนเอง
Vue.js ใช้กฏต่าง ๆ ในการตรวจจับการเปลี่ยนแปลงของข้อมูลและทำให้มันเป็น Reactive ดังนี้:
1.Object.defineProperty: Vue.js ใช้ Object.defineProperty เพื่อสร้าง Getters
และ Setters สำหรับคุณสมบัติของอ็อบเจกต์ ทำให้ Vue.js สามารถตรวจจับการเปลี่ยนแปลง
ของคุณสมบัติได้และอัพเดต View ตามความเปลี่ยนแปลงนั้น
2.Observer: Vue.js มีตัว Observer ที่สังเกตการเปลี่ยนแปลงของข้อมูลที่ถูกใช้ในโค้ด
Vue.js และแจ้งเตือน Vue.js เมื่อมีการเปลี่ยนแปลง
3.Reactivity System: Vue.js มีระบบ Reactivity ที่ประมวลผลและติดตามความ
เปลี่ยนแปลงของข้อมูลอัตโนมัติ ทำให้มันเป็นเหมือน Reactivity System ที่สามารถ
ติดตามและอัพเดตข้อมูลอัตโนมัติโดยไม่ต้องตรวจสอบเงื่อนไขโดยตรง
เมื่อข้อมูลถูกทำให้เป็น Reactive แล้ว การเปลี่ยนแปลงของข้อมูลที่ถูกใช้ในแอพพลิเคชั่น Vue.js
จะถูกตรวจจับอัตโนมัติ และอัพเดต View ในเวลาเดียวกันโดยไม่ต้องมีการสั่งให้มันอัพเดตโดยตรง
นี่คือเหตุผลที่ Vue.js เป็นเครื่องมือที่สามารถพัฒนาแอพพลิเคชั่นเรียลไทม์ได้อย่างมีประสิทธิภาพ
และง่ายต่อการบำรุงรักษาและจัดการ
การกำหนด Reactive State
รูปแบบการกำหนด reactive state เราน่าจะคุ้นมาบ้างแล้วจากตัวอย่างๆที่ผ่านมา
import { ref } from 'vue' const count = ref(0) const count = 0 // ถ้ากำหนดแบบไม่ใช้ฟังก์ชั่น ref() ตัวแปร count หากมีการเปลี่ยนแปลง // ก็จะไม่มีผลให้ DOM มีการ rendor หรืออัพเดท HTML ใหม่ ดึงนั้นจึงมีการใช้งาน ref()
ดูตัวอย่างไฟล์ App.vue นี้ประกอบการอธิบาย
<script setup> import { ref } from 'vue' const count = ref(0) function increment() { count.value++ } </script> <template> <button @click="increment"> {{ count }} </button> </template>
ส่วน <script setup> คือเทคนิคใหม่ใน Vue 3 ที่ช่วยให้เราสร้างคอมโพเนนต์ได้อย่างสั้นและ
กระชับมากขึ้น โดยทำการเขียนโค้ด JavaScript และประกาศความสัมพันธ์ของตัวแปรทั้งหมด
ในส่วนนี้
1.<script setup>: เริ่มต้นด้วยบล็อก <script setup> ซึ่งใช้เพื่อระบุว่าเราจะเขียนโค้ด
JavaScript สำหรับคอมโพเนนต์นี้ โดย Vue 3 จะทำการจัดการการสร้าง Reactivity
และประกาศตัวแปรให้เราอัตโนมัติ
2.import { ref } from 'vue': เรียกใช้งาน ref จาก Vue เพื่อสร้าง reactive reference
ใน JavaScript
3.const count = ref(0): ประกาศตัวแปร count โดยใช้ ref() เพื่อสร้าง reactive reference
ที่มีค่าเริ่มต้นเป็น 0
4.function increment(): ประกาศฟังก์ชัน increment() ซึ่งจะเพิ่มค่าของ count ทีละหนึ่งทุก
ครั้งที่ถูกเรียกใช้
ส่วน <template> เป็นส่วนที่ใช้สำหรับเขียน HTML Template ของคอมโพเนนต์
5.<button @click="increment">: สร้างปุ่มที่เมื่อคลิกจะเรียกใช้ฟังก์ชัน increment()
6.{{ count }}: แสดงค่าของตัวแปร count ภายในปุ่ม โดย Vue 3 จะทำการทำ reactive
binding โดยอัตโนมัติ ซึ่งหมายความว่าข้อมูลจะถูกอัพเดตอัตโนมัติเมื่อมีการเปลี่ยนแปลง
ทำให้ข้อมูลที่แสดงผลบนหน้าเว็บถูกอัพเดตอัตโนมัติและโชว์ผลลัพธ์ล่าสุดทุกครั้งที่มีการเปลี่ยนแปลง
การใช้ฟังก์ชั่น ref() จะทำให้ได้ object ที่มี value property ดังรูปตัวอย่าง
![](https://i.imgur.com/fY8462M.jpeg)
หากต้องการเปลี่ยนแปลงค่าในส่วนของ script เราต้องกำหนดค่าผ่าน value property
ตัวอย่างเช่น การเพิ่มค่า ก็จะใช้เป็น count.value++
แต่เวลาเรานำไปใช้งานเพื่อแสดงข้อมูลใน template จะไม่ต้องกำหนด .value นั่นคือ
ไม่ต้องกำหนดเป็น {{ count.value }} แต่ใช้เป็น {{ count }} แทนได้เลย
การกำหนดค่า Reactive State ด้วย ref()
เราสามารถกำหนดชนิดข้อมูลใดๆ ก็ได้ด้วยฟังก์ชั่น ref() รวมถึงอ็อบเจกต์ที่มีโครงสร้างที่ซับซ้อน
และมีการซ้อนกันของคุณสมบัติภายในอีกเป็นบรรทัดๆ รวมถึงพวก array หรือ Map ที่เป็นรูป
แบบโครงสร้างข้อมูลของ JavaScript ดูตัวอย่างโครงสร้างข้อมูลที่ซับซ้อนด้านล่างประกอบ
import { ref } from 'vue' const obj = ref({ nested: { count: 0 }, arr: ['foo', 'bar'] }) function mutateDeeply() { obj.value.nested.count++ obj.value.arr.push('baz') }
คำอธิบายการทำงาน
1.const obj = ref({ nested: { count: 0 }, arr: ['foo', 'bar'] }): สร้าง reactive
reference ชื่อ obj ที่มีค่าเริ่มต้นเป็น object ที่ประกอบด้วย property ชื่อ nested
ที่มี property count และ property ชื่อ arr ที่มีค่าเริ่มต้นเป็น array ['foo', 'bar']
2.function mutateDeeply() { ... }: ประกาศฟังก์ชัน mutateDeeply() ซึ่งมีการเข้าถึง
และเปลี่ยนแปลงข้อมูลภายใน obj โดยการเพิ่มค่าใน count ของ nested และเพิ่มค่าใหม่
ลงใน arr
3.obj.value.nested.count++: เข้าถึงค่า nested ใน obj และเพิ่มค่า count อีกหนึ่ง
เมื่อ mutateDeeply() ถูกเรียก
4.obj.value.arr.push('baz'): เข้าถึง array arr ใน obj และเพิ่มค่า 'baz' เข้าไปใน array
นั้นเมื่อ mutateDeeply() ถูกเรียก
การใช้งานฟังก์ชัน reactive() เพื่อกำหนด Reactive State
นอกจากการใช้งานฟังก์ชั่น ref() ก็ยังไมีฟังก์ชั่น reactive() ที่ใช้สำหรับกำหนด State ซึ่ง
ความแต่งของทั้งสองวิธีเป็นดังนี้
ref():
1.ref() ใช้สำหรับสร้าง reactive reference หรือ reference ที่เป็น reactive
ในรูปแบบของค่าเดียว (primitive value) เช่น number, string, boolean,
หรือ object หนึ่งตัว
2.เมื่อใช้ ref() เราต้องเข้าถึงค่าใน reference ด้วย .value เพื่อทำการอ่านหรือ
เปลี่ยนแปลงค่า
3.เหมาะสำหรับใช้กับค่าที่เปลี่ยนแปลงบ่อยและต้องการ reactivity อย่างง่าย
reactive():
1.reactive() ใช้สำหรับสร้าง reactive objects ซึ่งเป็น reactive ทั้งหมด
คือทุก property ภายใน object นั้นเป็น reactive ไม่ว่าจะเป็น primitive value
หรือ object อื่น ๆ
2.เมื่อใช้ reactive() เราไม่จำเป็นต้องใช้ .value เพื่อเข้าถึงค่า แต่สามารถเข้าถึงค่าได้โดยตรง
3.เหมาะสำหรับใช้กับ object ที่มีโครงสร้างที่ซับซ้อนและต้องการ reactivity ในทุก
property ของ object นั้น
ตัวอย่างการกำหนด state ด้วยฟังก์ชั่น reactive()
<script setup> import { reactive } from 'vue' const state = reactive({ count: 0 }) console.log(state) function increment() { state.count++ } </script> <template> <button @click="increment"> {{ state.count }} </button> </template>
สังเกตว่าเมื่อเราใช้งานฟังก์ชั่น reactive() ก็จะสามารถอ้างอิงค่าตัวแปรโดยไม่ต้องผ่าน
.value property เนื่องจากจะไม่มีค่านี้ และ reactive object ที่ถูกสร้างขึ้นก็จะเป็น
ในรูปแบบของ JavaScript Proxies ที่ทำงานเหมือน object ปกติทั่วไป
![](https://i.imgur.com/PJyEVIb.jpeg)
อย่างไรก็ดีฟังก์ชั่นนี้ก็มีข้อจำกัด เช่น ไม่สามารถใช้กำหนดชนิดข้อมูลพื้นฐานได้ เช่น ตัวเลข
ข้อความ ค่า boolean และตัวแปรพื้นฐานอื่นๆ ที่ไม่สามารถแยกต่อได้ โดยฟังก์ชั่นนี้จะ
เหมาะกับตัวแปร object, arrays, Map และ Set ที่มีความซับซ้อนมากกว่า ข้อจำกัดต่อมา
ก็คือไม่สามารถแทนค่าอ้อปเจกต์ทั้งหมดด้วยค่าใหม่ทีเดียวได้ และสุดท้ายคือเมื่อทำการ
destructuring หรือการแยกค่าจาก object หรือ array เป็นตัวแปรทีละชิ้น จะไม่สะดวกใน
การใช้งาน เพราะโค้ดมีโครงสร้างที่ซับซ้อนหรือไม่เข้ากันได้กับการใช้งาน destructuring
อย่างไม่สมบูรณ์ ตัวอย่างเช่น
const state = reactive({ count: 0 }) // เมื่อมีการ destructuring ตัวแปร count จะหลุดการเชื่อมต่อกับ // state.count หรือก็คือตัวแปร count ไม่มีผลกับการเปลี่ยนแปลงค่า state let { count } = state // ไม่มีผลกับการเปลี่ยนแปลงค่า state count++ // หรือกรณีนำเข้าไปในฟังก์ชั่น ก็จะไม่มีผลกับการเปลี่ยนแปลงของ state callSomeFunction(state.count)
ด้วยข้อจำกัดดังกล่าวข้างต้น ดังนั้นจึงแนะนำให้ใช้ฟังก์ชั่น ref() เป็นฟังก์ชั่นหลักในการ
กำหนดตัวแปรสำหรับ reactive state