ข้ามไปยังเนื้อหา

Runes vs Stores

ก่อน Svelte 5 การ share reactive state ข้ามคอมโพเนนต์หมายถึง store ตอนนี้คุณเอา $state ไปไว้ใน module แล้ว export ได้ runes ทำงานนอกคอมโพเนนต์ได้ — แต่เฉพาะในไฟล์นามสกุล .svelte.js หรือ .svelte.ts ซึ่งบอก compiler ให้เปิดการประมวลผล rune

เวอร์ชัน store:

counter.js
import { writable } from 'svelte/store';
export const count = writable(0);
<script>
import { count } from './counter.js';
</script>
<button onclick={() => count.update((n) => n + 1)}>{$count}</button>

เวอร์ชัน runes:

// counter.svelte.js ← note the .svelte.js extension
export const counter = $state({ value: 0 });
<script>
import { counter } from './counter.svelte.js';
</script>
<button onclick={() => counter.value++}>{counter.value}</button>

ไม่มี writable ไม่มี set/update ไม่มี prefix $ — คุณอ่านและ mutate counter.value เหมือน object ธรรมดา และ reactive ทุกที่ที่ใช้

สังเกตว่าเวอร์ชัน runes export { value: 0 } ไม่ใช่ 0 การ export let x = $state(0) เปล่า ๆ จะคง link ข้าม module boundary ไว้ไม่ได้ — การ import จะ copy ค่าและเสีย reactivity ไป การ export object (หรือฟังก์ชันที่ return reactive state) ทำให้ทุกคนยังชี้ไปที่ reactive proxy ตัวเดียวกัน ดังนั้น mutation ที่ counter.value จึงกระจายไป นี่คือ gotcha ข้อเดียวของ module-level runes

Store (writable)Runes (.svelte.js)
อ่านในคอมโพเนนต์$countcounter.value
อัปเดตcount.set(x) / count.update(fn)counter.value = x
นอกคอมโพเนนต์ใช้ได้ทุกที่ต้องใช้ .svelte.js/.svelte.ts
subscribe contractมี (interop, observable)ไม่มี
พิธีการมากกว่า (method, $)น้อยกว่า (อ่าน/เขียนตรง ๆ)
flowchart TB
  q["share reactive state ไหม"] --> interop["ต้องการ subscribe contract ไหม (observable, external push source)"]
  interop --> yes["ใช่: ใช้ store"]
  interop --> no["ไม่: export state จาก .svelte.js module"]
เลือก runes หรือ stores
  • runes (default) app state ที่ share ส่วนใหญ่ — cart, theme, current-user object ง่ายกว่า boilerplate น้อยกว่า และ mental model เดียวกับ component-local state
  • stores เมื่อคุณต้องการ contract: ห่อ WebSocket หรือ push source อื่นด้วย readable, interop กับ observable แบบ RxJS หรือดูแล code ที่ใช้ store อยู่แล้ว stores ไม่ใช่ของเก่า — แต่เป็นเครื่องมือเฉพาะทาง
คุณใช้ runes สำหรับ state นอกคอมโพเนนต์ยังไง?
ทำไมต้อง export object อย่าง `$state({ value: 0 })` แทน `$state(0)` เปล่า ๆ?
ในเวอร์ชัน runes คุณอัปเดต shared state ยังไง?
เมื่อไรที่ stores เป็นตัวเลือกที่ดีกว่า runes?