01ref, reactive, computed และ watch
ref()เหมาะกับค่าเดี่ยวและ object ที่อาจถูกแทนทั้งก้อน อ่านและเขียนผ่าน `.value` ใน JavaScript
reactive()คืน Proxy ของ object เหมาะกับ state แบบกลุ่ม แต่ destructure property ตรง ๆ อาจทำให้หลุด reactivity
computed()ใช้กับค่าที่ derive จาก state ไม่มี side effect และ cache จน dependency เปลี่ยน
watch()ใช้ทำ side effect เช่นเรียก API, sync URL หรือ analytics และต้อง cleanup งานเก่า
<script setup lang="ts">
import { computed, onWatcherCleanup, ref, watch } from 'vue'
const query = ref('')
const policies = ref<Policy[]>([])
const activePolicies = computed(() =>
policies.value.filter((item) => item.status === 'ACTIVE')
)
watch(query, async (value) => {
const controller = new AbortController()
onWatcherCleanup(() => controller.abort())
policies.value = await searchPolicies(value, controller.signal)
})
</script>ในตัวอย่าง `activePolicies` เป็นข้อมูลที่คำนวณจาก state จึงใช้ `computed` ส่วน search API เป็น side effect จึงใช้ `watch` และยกเลิก request เก่าเมื่อ query เปลี่ยน ป้องกัน race ที่ response เก่ากลับมาทับผลใหม่
02แบ่ง State ตามเจ้าของ
Component state
เปิด/ปิด dialog, form draft และ UI state ที่ไม่มี component อื่นต้องรู้
Pinia
session, permission หรือ workflow ที่หลาย route และ component ใช้ร่วมกัน
Remote data
ข้อมูลจาก API ที่มี loading, error, cache และ invalidation lifecycle ของตัวเอง
อย่าย้ายทุกอย่างเข้า global store เพราะทำให้ dependency ซ่อนอยู่และ lifecycle ยาวเกินจำเป็น เริ่มจาก state ที่ใกล้ผู้ใช้ที่สุด แล้วเลื่อนขึ้นเมื่อมี consumer ร่วมจริง
Composable ควรห่อ logic ที่ reuse ได้และมี contract ชัด ไม่ใช่แค่ย้ายโค้ดออกจาก component ถ้า composable เข้าถึง global store, router และ API พร้อมกันโดยซ่อน dependency ทั้งหมด การทดสอบและ reuse จะยากขึ้น
03Performance ที่ควรตรวจตามลำดับ
- 1วัดก่อน
ใช้ Vue DevTools และ browser performance หา component ที่ update บ่อยจริง
- 2ลดงานที่ส่งลง client
route lazy loading และ code splitting สำหรับ feature ใหญ่
- 3ลดจำนวน DOM
virtualize list ยาว และใช้ stable key ที่แทน identity จริง
- 4ลด reactive overhead
ข้อมูลก้อนใหญ่ที่ไม่ต้อง deep reactive ใช้ `shallowRef` หรือ mark raw อย่างมีเหตุผล
อย่า optimize ด้วย `v-memo`, shallow API หรือ manual cache ก่อนมี evidence เพราะ complexity ที่เพิ่มอาจแพงกว่าปัญหาเดิม โดยเฉพาะ component ที่ render ไม่บ่อย