状态管理深入

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 下状态的 getput 操作都会自动延长该 ID 下所有状态的生命周期。

4. 最佳实践

何时使用 Nex.Store?

  • 临时累积:如购物车,用户在当前页面不断添加商品。
  • 交互反馈:存储异步操作后的中间结果。
  • 跨 Action 共享:在页面的不同交互函数之间传递上下文。

什么时候不该使用?

  • 敏感数据:不要将用户密码或密钥存在内存 Store 中。
  • 大数据量:Store 适合存储元数据和小型结构,不适合存储几百 MB 的文件内容。
  • 关键持久化:如果数据在用户刷新后必须存在(如已完成的订单),请务必写入数据库。

5. 调试技巧

在开发模式下,你可以利用 Elixir 控制台查看当前 Store 的状况:

# 查看所有活跃的状态键值
:ets.tab2list(:nex_store)