SvelteKit 的状态管理,比很多纯客户端应用更讲边界。
因为这里有两种空间:
- 浏览器里的前台状态
- 服务端请求期的后台状态
你要把它们分开想。
#一类:纯前台局部状态
比如:
- 当前展开的说明面板
- 选中的座位
- 弹窗开关
- 局部 loading
这种就用组件本地状态,最自然:
<script lang="ts">
let expanded = $state(false);
</script>
<button onclick={() => expanded = !expanded}>
{expanded ? '收起剧评' : '展开剧评'}
</button>
{#if expanded}
<aside>这是一段幕后访谈</aside>
{/if}#二类:应该进入 URL 的状态
比如:
- 搜索关键字
- 筛选条件
- 分页页码
- 排序方式
这种不要死塞本地状态,更适合放进 URL。
因为这类状态本来就是“这一张票面上应该写出来的信息”。
/plays?q=莎士比亚&page=2&sort=opensAt这样做的好处:
- 可分享
- 可刷新恢复
- 可被
load直接消费 - SSR/CSR 都一致
#三类:请求期身份与权限状态
比如:
- 当前用户
- 当前组织
- 权限集合
- session 信息
这类不要放共享服务端变量,应该来自:
- cookie
event.locals- server load
- 数据库/缓存
#四类:跨页面但不适合进 URL 的短暂前台状态
比如:
- 用户刚刚填写到一半的复杂草稿
- 同一次会话中的临时 UI 记忆
可以考虑:
- 布局层 context/store
- 浏览器存储
- SvelteKit 的 snapshots(适用于某些短暂页面状态场景)
但核心原则不变:
能写进 URL 的,优先写进 URL
只属于当前组件的,就留在组件里
涉及身份/安全/私密的,不要伪装成前端状态