Persist 插件
Alpine 的 Persist 插件允许你在页面加载之间持久化 Alpine 状态。
这对于持久化搜索过滤器、活动选项卡以及其他功能非常有用,这些情况下用户在刷新或离开并重新访问页面时,其配置被重置会感到沮丧。
安装
你可以通过 <script> 标签引入或通过 NPM 安装来使用此插件:
通过 CDN
你可以将此插件的 CDN 构建版本作为 <script> 标签引入,只需确保在 Alpine 核心 JS 文件之前引入。
<!-- Alpine 插件 -->
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
<!-- Alpine 核心 -->
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
通过 NPM
你可以从 NPM 安装 Persist 以在打包中使用:
npm install @alpinejs/persist
然后从你的打包工具中初始化它:
import Alpine from 'alpinejs'
import persist from '@alpinejs/persist'
Alpine.plugin(persist)
...
$persist
使用此插件的主要 API 是 $persist 魔法方法。
你可以像下面这样将 x-data 中的任何值用 $persist 包裹,以在页面加载之间持久化其值:
<div x-data="{ count: $persist(0) }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
在上面的示例中,因为我们用 $persist() 包裹了 0,Alpine 现在会拦截对 count 所做的更改,并在页面加载之间持久化它们。
你可以亲自尝试:在上面的示例中增加"count",然后刷新此页面,观察"count"是否保持其状态而不是重置为"0"。
它是如何工作的?
如果一个值用 $persist 包裹,在初始化时 Alpine 会为该值注册自己的监听器。现在每当该值因任何原因发生变化时,Alpine 都会将新值存储在 localStorage 中。
现在当页面重新加载时,Alpine 会检查 localStorage(使用属性名称作为键)以查找值。如果找到了,它会立即从 localStorage 设置属性值。
你可以通过打开浏览器开发者工具的 localStorage 查看器来观察此行为:
你会注意到,只要访问此页面,Alpine 就已经在 localStorage 中设置了"count"的值。你还会注意到它将属性名"count"添加了前缀 _x_,作为命名空间这些值的方式,使 Alpine 不会与使用 localStorage 的其他工具冲突。
现在更改以下示例中的"count",并观察 Alpine 对 localStorage 所做的更改:
<div x-data="{ count: $persist(0) }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
$persist适用于原始值以及数组和对象。 然而,值得注意的是,当变量的类型发生变化时,localStorage 必须被清除。
根据前面的示例,如果我们将 count 改为$persist({ value: 0 })的值,那么必须清除 localStorage 或重命名变量'count'。
设置自定义键
默认情况下,Alpine 使用 $persist(...) 被分配到的属性键(在上述示例中为"count")。
考虑这样一种场景:你有多个 Alpine 组件分布在多个页面上,甚至在同一个页面上,它们都使用"count"作为属性键。
Alpine 将无法区分这些组件。
在这些情况下,你可以使用 .as 修饰符为任何持久化值设置自己的自定义键,如下所示:
<div x-data="{ count: $persist(0).as('other-count') }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
现在 Alpine 将使用键"other-count"来存储和检索上面的"count"值。
以下是 Chrome Devtools 的视图,供你亲自查看:

使用自定义存储
默认情况下,数据保存到 localStorage,它没有过期时间,即使在页面关闭后也会保持。
考虑这样一种场景:你希望在用户关闭标签页时清除数据。在这种情况下,你可以使用 .using 修饰符将数据持久化到 sessionStorage,如下所示:
<div x-data="{ count: $persist(0).using(sessionStorage) }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
你也可以定义自己的自定义存储对象,暴露一个 getItem 函数和一个 setItem 函数。例如,你可以决定使用会话 cookie 作为存储:
<script>
window.cookieStorage = {
getItem(key) {
let cookies = document.cookie.split(";");
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].split("=");
if (key == cookie[0].trim()) {
return decodeURIComponent(cookie[1]);
}
}
return null;
},
setItem(key, value) {
document.cookie = key+' = '+encodeURIComponent(value)
}
}
</script>
<div x-data="{ count: $persist(0).using(cookieStorage) }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
将 $persist 与 Alpine.data 一起使用
如果你想将 $persist 与 Alpine.data 一起使用,你需要使用标准函数而不是箭头函数,这样 Alpine 才能在初始评估组件作用域时绑定自定义的 this 上下文。
Alpine.data('dropdown', function () {
return {
open: this.$persist(false)
}
})
使用 Alpine.$persist 全局
Alpine.$persist 是全局暴露的,因此可以在 x-data 上下文之外使用。这对于持久化来自其他源(如 Alpine.store)的数据很有用。
Alpine.store('darkMode', {
on: Alpine.$persist(true).as('darkMode_on')
});
