状态管理深入
Nex 提供了一套独特的状态管理哲学,旨在解决现代 Web 开发中“状态爆炸”的问题。
1. 状态的分层
在 Nex 应用中,状态通常分为三层:
| 维度 | 客户端状态 (如 Alpine.js)* | 页面状态 (Nex.Store) | 持久化状态 (DB) |
|---|---|---|---|
| 存储位置 | 浏览器内存 | 服务器内存 (ETS) | 磁盘 (PostgreSQL/Etc) |
| 生命周期 | 页面加载期间 | 页面 ID 生命周期内 | 永久(直到删除) |
| 适用场景 | 菜单开关、即时预览 | 购物车、临时表单、搜索过滤 | 用户资料、订单数据 |
| 同步开销 | 0(本地) | 低(AJAX) | 高(DB IO) |
\注:Nex 默认不引入客户端 JS 库。如果你根据需要引入了 Alpine.js 或 Datastar,则可以使用此类状态。*
2. Nex.Store 设计初衷:Ephemeral State
Nex.Store 专门为 Ephemeral State(易失性状态) 设计。
为什么选择易失性?
在 HTMX 的交互模型中,我们经常需要存储一些“比请求长,但比会话短”的数据。例如:
- 用户在多步骤表单中填写了一半的数据。
- 当前页面的排序和筛选条件。
- 侧边栏的折叠状态。
通过绑定 page_id,Nex 确保了这些状态在用户刷新页面时自动清理,避免了传统 Session 机制中常见的“脏状态”残留问题。
3. ETS 实现与性能
Nex.Store 底层使用 Erlang 的 ETS (Erlang Term Storage) 表实现:
- 并发性:ETS 支持极高的并发读写,适合处理大量用户的实时交互。
- 内存驻留:数据存储在内存中,访问速度极快。
-
TTL 清理:
-
每条记录都有一个
expires_at戳。 -
后台
Nex.Store.Janitor进程定期扫描并删除过期记录。 -
自动续期:任何对特定
page_id下状态的get或put操作都会自动延长该 ID 下所有状态的生命周期。
-
每条记录都有一个
4. 最佳实践
何时使用 Nex.Store?
- 临时累积:如购物车,用户在当前页面不断添加商品。
- 交互反馈:存储异步操作后的中间结果。
- 跨 Action 共享:在页面的不同交互函数之间传递上下文。
什么时候不该使用?
- 敏感数据:不要将用户密码或密钥存在内存 Store 中。
- 大数据量:Store 适合存储元数据和小型结构,不适合存储几百 MB 的文件内容。
- 关键持久化:如果数据在用户刷新后必须存在(如已完成的订单),请务必写入数据库。
5. 调试技巧
在开发模式下,你可以利用 Elixir 控制台查看当前 Store 的状况:
# 查看所有活跃的状态键值
:ets.tab2list(:nex_store)