状态管理 (Nex.Store)

在传统的 Web 开发中,管理异步交互的状态(如购物车、临时表单数据)往往很麻烦。Nex 提供了一个名为 Nex.Store 的简单、基于页面的服务端状态存储机制。

1. 核心概念

Nex.Store 的设计哲学是:状态应当与当前的页面生命周期绑定。

  • Ephemeral (易失性):状态在页面刷新(全页加载)时会自动重置。
  • Persistent (在交互中保持):状态在 HTMX 异步请求(Action 调用)中持续保持。
  • 隔离性:每个浏览器标签页(甚至同一个页面的不同窗口)的状态都是相互隔离的。

2. 常用操作

Nex.Store 提供了类似于 Map 的操作接口:

读取状态

# 获取键为 :items 的值,如果不存在则返回默认值 []
items = Nex.Store.get(:items, [])

存储状态

# 直接设置键为 :user_name 的值
Nex.Store.put(:user_name, "Alice")

更新状态

# 使用函数更新状态(原子操作)
Nex.Store.update(:count, 0, &(&1 + 1))

删除状态

Nex.Store.delete(:items)

3. page_id 的工作原理

这是 Nex 状态管理的核心。

  1. 生成:每当你刷新页面(发起一个标准的 GET 请求),Nex 都会生成一个新的随机 page_id
  2. 绑定:所有的 Nex.Store 操作实际上都存储为 {page_id, key} -> value
  3. 追踪:Nex 会自动在页面中注入一段脚本。当 HTMX 发起请求时,脚本会自动添加 X-Nex-Page-Id 请求头。
  4. 失效:当你点击浏览器刷新,或者直接输入 URL 访问,你会得到一个新的 page_id。旧的状态由于找不到对应的 ID,在服务端看起来就像是“重置”了。

提示:这正是 Nex 的设计初衷——模拟用户在当前页面的临时记忆。如果你需要跨页面、跨会话的持久化状态,请使用传统的数据库(如 PostgreSQL)。

4. 自动清理 (TTL)

为了防止内存泄漏,Nex 会自动清理过期的状态:

  • 默认过期时间:1 小时。
  • 每次通过 Nex.Store 访问或更新状态时,过期时间都会自动刷新。
  • 服务端有一个后台进程每 5 分钟执行一次全量清理。

练习:购物车原型

创建一个 src/pages/cart.ex

  1. mount 中读取 :cart_items
  2. 添加一个表单来添加商品名称。
  3. 在 Action add_item 中使用 Nex.Store.update 将新商品加入列表。
  4. 观察:在添加了几个商品后,点击浏览器刷新,购物车是否如预期般变空了?