From 3aef43d56936ce48960bb8c3922344829a621bd4 Mon Sep 17 00:00:00 2001 From: lichong <1546214265@qq.com> Date: Wed, 25 Sep 2024 18:04:52 +0800 Subject: [PATCH 1/4] Translate Chinese --- docs/.vitepress/config/index.ts | 2 + docs/.vitepress/config/zh.ts | 83 +++++++++++ docs/zh/frameworks/nuxt.md | 192 ++++++++++++++++++++++++ docs/zh/frameworks/others.md | 6 + docs/zh/guide/advanced.md | 169 +++++++++++++++++++++ docs/zh/guide/config.md | 250 ++++++++++++++++++++++++++++++++ docs/zh/guide/index.md | 74 ++++++++++ docs/zh/guide/limitations.md | 52 +++++++ docs/zh/guide/why.md | 24 +++ 9 files changed, 852 insertions(+) create mode 100644 docs/.vitepress/config/zh.ts create mode 100644 docs/zh/frameworks/nuxt.md create mode 100644 docs/zh/frameworks/others.md create mode 100644 docs/zh/guide/advanced.md create mode 100644 docs/zh/guide/config.md create mode 100644 docs/zh/guide/index.md create mode 100644 docs/zh/guide/limitations.md create mode 100644 docs/zh/guide/why.md diff --git a/docs/.vitepress/config/index.ts b/docs/.vitepress/config/index.ts index f4b9819..5d791e0 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -3,6 +3,7 @@ import { defineConfig } from 'vitepress' import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons' import { algolia } from './algolia' import { en } from './en' +import { zh } from './zh' export default defineConfig({ title: 'Pinia Plugin Persistedstate', @@ -71,5 +72,6 @@ export default defineConfig({ lang: 'en', ...en, }, + zh: { label: '简体中文', ...zh } }, }) diff --git a/docs/.vitepress/config/zh.ts b/docs/.vitepress/config/zh.ts new file mode 100644 index 0000000..485a651 --- /dev/null +++ b/docs/.vitepress/config/zh.ts @@ -0,0 +1,83 @@ +import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress' +import { version } from '../../../package.json' + +export const zh: LocaleSpecificConfig = { + description: 'Pinia stores的可配置持久性.', + themeConfig: { + editLink: { + text: '建议对此页面进行更改', + pattern: 'https://github.com/prazdevs/pinia-plugin-persistedstate/edit/main/docs/:path', + }, + nav: [ + { + text: '指南', + link: '/zh/guide/', + activeMatch: '/zh/guide/', + }, + { + text: '框架', + items: [ + { text: 'Nuxt', link: '/zh/frameworks/nuxt' }, + { text: '其他框架', link: '/zh/frameworks/others' }, + ], + }, + { + text: `v${version}`, + items: [ + { + items: [{ + text: '发行说明', + link: 'https://github.com/prazdevs/pinia-plugin-persistedstate/releases', + }], + }, + { + text: '版本', + items: [ + { + text: `${version} (Current)`, + activeMatch: '/', + link: '#', + }, + { + text: '3.2.2', + link: 'https://github.com/prazdevs/pinia-plugin-persistedstate/tree/v3', + }, + { + text: '2.4.0', + link: 'https://github.com/prazdevs/pinia-plugin-persistedstate/tree/v2', + }, + { + text: '1.6.3', + link: 'https://github.com/prazdevs/pinia-plugin-persistedstate/tree/v2', + }, + ], + }, + ], + }, + ], + sidebar: [ + { + text: '指南', + items: [ + { text: '为什么使用这个插件?', link: '/zh/guide/why' }, + { text: '开始', link: '/zh/guide/' }, + { text: '配置', link: '/zh/guide/config' }, + { text: '局限性', link: '/zh/guide/limitations' }, + { text: '高级用法', link: '/zh/guide/advanced' }, + ], + }, + { + text: '框架', + items: [ + { text: 'Nuxt', link: '/frameworks/nuxt' }, + { text: '其他框架', link: '/frameworks/others' }, + ], + }, + ], + footer: { + message: '在 MIT 许可证下发布。', + copyright: '版权所有 © 2021 年至今 Sacha Bouillez 及贡献者', + }, + + }, +} diff --git a/docs/zh/frameworks/nuxt.md b/docs/zh/frameworks/nuxt.md new file mode 100644 index 0000000..f127832 --- /dev/null +++ b/docs/zh/frameworks/nuxt.md @@ -0,0 +1,192 @@ +# Usage with Nuxt + +该软件包 `pinia-plugin-persistedstate` 附带一个 Nuxt 模块,可提供开箱即用的 SSR 友好体验。 + +## 安装 + +1. 使用你喜欢的包管理器安装依赖项: + ::: code-group + ```sh [pnpm] + pnpm add pinia-plugin-persistedstate + ``` + ```sh [npm] + npm i pinia-plugin-persistedstate + ``` + ```sh [yarn] + yarn add pinia-plugin-persistedstate + ``` + ::: + +1. 将模块添加到 Nuxt 配置中: +```ts [nuxt.config.ts] +export default defineNuxtConfig({ + modules: [ + '@pinia/nuxt', + 'pinia-plugin-persistedstate/nuxt', + ], +}) +``` + +## 用法 + +在声明您的存储时,将新的 `persist` 选项设置为 `true`。 + +::: code-group +```ts{11} [setup syntax] +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export const useStore = defineStore( + 'main', + () => { + const someState = ref('hello pinia') + return { someState } + }, + { + persist: true, + }, +) +``` +```ts{9} [option syntax] +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => { + return { + someState: 'hello pinia', + } + }, + persist: true, +}) +``` +::: + +## 预配置 + +Nuxt 模块预配置了以下内容: + +- [`cookies`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) 作为存储。 +- [`store.$id`](https://pinia.vuejs.org/api/interfaces/pinia.StoreProperties.html) 作为 storage 的默认 key。 +- [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)/[`destr`](https://github.com/unjs/destr) 作为序列化器/反序列化器。 +- 整个状态将持久化到存储中。 + +## 选择存储 + +您可以通过使用自动导入的 `piniaPluginPersistedstate` 变量下的可用存储来配置要使用的存储。 + +> [!WARNING] +> 使用 `persistedState` 公开的存储之外的其他存储可能会出现意外行为。 + +### `cookies` + +```ts{10} +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => { + return { + someState: 'hello pinia', + } + }, + persist: { + storage: piniaPluginPersistedstate.cookies(), + }, +}) +``` + +> [!TIP] +> `persistedState.Cookies` 方法接受一个对象参数来配置带有以下选项的cookie(从Nuxt的 `useCookie` 继承而来): +> - [`domain`](https://nuxt.com/docs/api/composables/use-cookie#domain) +> - [`expires`](https://nuxt.com/docs/api/composables/use-cookie#maxage-expires) +> - [`httpOnly`](https://nuxt.com/docs/api/composables/use-cookie#httponly) +> - [`maxAge`](https://nuxt.com/docs/api/composables/use-cookie#maxage-expires) +> - [`partitioned`](https://nuxt.com/docs/api/composables/use-cookie#partitioned) +> - [`path`](https://nuxt.com/docs/api/composables/use-cookie#path) +> - [`sameSite`](https://nuxt.com/docs/api/composables/use-cookie#samesite) +> - [`secure`](https://nuxt.com/docs/api/composables/use-cookie#secure) + +### `localStorage` + +```ts{10} +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => { + return { + someState: 'hello pinia', + } + }, + persist: { + storage: piniaPluginPersistedstate.localStorage(), + }, +}) +``` + +> [!WARNING] +> `localStorage` 仅限客户端。 + +### `sessionStorage` + +```ts{10} +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => { + return { + someState: 'hello pinia', + } + }, + persist: { + storage: piniaPluginPersistedstate.sessionStorage(), + }, +}) +``` + +> [!WARNING] +> `sessionStorage` 仅限客户端。 + +## Global options + +该模块接受在 `piniaPluginPersistedstate` key下的 `nuxt.config.ts` 中定义的一些选项: + +- [`cookieOptions`](#cookies) +- `debug` +- [`key`](#global-key) +- `storage` + +> [!NOTE] +> 全局存储选项仅接受预配置存储 (`'cookies'`, `'localStorage'`, `'sessionStorage'`)的字符串值。 这是由于 Nuxt 将 [模块选项传递给运行时](https://nuxt.com/docs/guide/going-further/modules#exposing-options-to-runtime)的方式。 + +```ts{6-12} [nuxt.config.ts] +export default defineNuxtConfig({ + modules: [ + '@pinia/nuxt', + 'pinia-plugin-persistedstate/nuxt' + ], + piniaPluginPersistedstate: { + storage: 'cookies', + cookieOptions: { + sameSite: 'lax', + }, + debug: true, + }, +}) +``` + +## 全局密钥 + +您可以为全局使用的前缀/后缀键提供模板字符串。提供的密钥必须包含令牌 `%id` ,该令牌将被相应的存储id替换。 + +```ts{6} [nuxt.config.ts] +export default defineNuxtConfig({ + modules: [ + '@pinia/nuxt', + 'pinia-plugin-persistedstate/nuxt' + ], + piniaPluginPersistedstate: { + key: 'prefix_%id_postfix', + }, +}) +``` + +任何以 `my-store` 作为持久key(用户提供或从商店id推断)的商店都将在 `prefix_my-store_postfix` key下持久化。 diff --git a/docs/zh/frameworks/others.md b/docs/zh/frameworks/others.md new file mode 100644 index 0000000..29d128f --- /dev/null +++ b/docs/zh/frameworks/others.md @@ -0,0 +1,6 @@ +# 与其他 Vue 框架一起使用 + +没有计划在 Nuxt 之外为 Vue 框架提供官方支持。但是,该插件应该可以在大多数框架中使用,就像任何 Pinia 插件一样。请注意潜在的 SSR 警告。 + +> [!IMPORTANT] +> 如果你想提供在Quasar、Ionic或Vike等框架中集成“pinia-plugin-persistedstate”的食谱,非常欢迎你 [为文档做出贡献](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/CONTRIBUTING.md)! diff --git a/docs/zh/guide/advanced.md b/docs/zh/guide/advanced.md new file mode 100644 index 0000000..60760ed --- /dev/null +++ b/docs/zh/guide/advanced.md @@ -0,0 +1,169 @@ +# 高级用法 + +该插件还为更高级的用例公开了其他 API。 + +## 全局持久性选项 + +安装插件时,您可以使用公开的 `createPersistedState` 方法来初始化带有全局选项的插件,而不是使用默认导出。这些选项成为应用程序中所有商店的新默认选项。 + +```ts twoslash +import { createPinia } from 'pinia' +import { createPersistedState } from 'pinia-plugin-persistedstate' + +const pinia = createPinia() + +pinia.use(createPersistedState({ + storage: sessionStorage, +})) +``` + +在此示例中,每个声明 `persist: true` 的存储将默认地将数据保存到 `sessionStorage` 中。 + +可用的全局选项包括: +- [`storage`](/guide/config#storage) +- [`serializer`](/guide/config#serializer) +- [`debug`](/guide/config#debug) + +传递给存储的 `persist` 配置的任何选项都将覆盖在全局选项中声明的对应选项。 + +> [!WARNING] 使用 NUXT ? +> Nuxt 模块中的全局选项作为模块选项处理,与独立的插件全局选项不同。在 [Nuxt 模块文档 ](/frameworks/nuxt)中阅读更多内容。 + +## 全局密钥选项 + +除了其他全局持久性选项之外,`createPersistedState` 函数还接受一个选项: `key`。全局 `key` 选项接受传递给存储键的函数,并且应该返回一个字符串,以成为新的存储key。 + +```ts twoslash +import { createPinia } from 'pinia' +import { createPersistedState } from 'pinia-plugin-persistedstate' + +const pinia = createPinia() + +pinia.use(createPersistedState({ + key: id => `__persisted__${id}`, +})) +``` + +```ts twoslash +import { defineStore } from 'pinia' + +defineStore('store', { + state: () => ({ saved: '' }), + persist: true, +}) +``` + +在此示例中,存储将在 `__persisted__store` 下而不是在 `store` 下持久化。 + +> [!WARNING] 使用 NUXT ? +> Nuxt 中的全局key通过 module 项作为字符串模板而不是函数传递。在 [Nuxt 模块文档 ](/frameworks/nuxt)中阅读更多内容。 + +## 存储的多个持久性 + +可能存在需要将数据从一个存储持久化到不同存储的特定用例。 `persist` 选项也接受数组配置。 + +```ts twoslash +import { defineStore } from 'pinia' + +defineStore('store', { + state: () => ({ + toLocal: '', + toSession: '', + toNowhere: '', + }), + persist: [ + { + pick: ['toLocal'], + storage: localStorage, + }, + { + pick: ['toSession'], + storage: sessionStorage, + }, + ], +}) +``` + +在本例中, `toLocal` 值将保存在 `localStorage` 中,而 `toSession` 值将保存在 `sessionStorage` 中。`toNowhere` 将不会持续。 + +:::warning +当不指定 `paths` 选项或在两个持久性配置中以同一路径为目标时要小心。这可能导致数据不一致。在rehydration过程中,持久性的处理顺序与声明的顺序相同。 + +```ts twoslash +import { defineStore } from 'pinia' + +defineStore('store', { + state: () => ({ + someData: 'Hello Pinia' + }), + persist: [ + { + storage: localStorage, + }, + { + storage: sessionStorage, + }, + ], +}) +``` + +在这种特定情况下,在水合时,从 `sessionStorage` 检索的数据将替换从 `localStorage` 检索的数据。 +::: + +## 强制 hydration + +如果您需要从存储中手动触发hydration作用,现在每个存储都公开了一个 `$hydrate` 方法。默认情况下,调用此方法还会触发 `beforeHydrate` 和 `afterHydrate` 钩子。您可以通过指定方法来避免钩子触发。 + +借鉴此 store: + +```ts twoslash +import { defineStore } from 'pinia' + +const useStore = defineStore('store', { + state: () => ({ + someData: 'Hello Pinia' + }) +}) +``` + +您可以访问 `$hydrate`: + +```ts +const store = useStore() + +store.$hydrate({ runHooks: false }) +``` + +这将从存储中获取数据并用它替换当前状态。在上面的例子中,钩子不会被触发。 + +> [!WARNING] +> 在大多数情况下,您应该不需要手动合并状态。确保你知道你在做什么,并且你使用 `$hydrate` 的原因不是由于一个错误(无论是你的实现还是插件本身)。 + +## Forcing the persistence + +如果您需要手动触发存储的持久性,现在每个存储都公开了一个 `$persist` 方法。 + +借鉴此 store: + +```ts twoslash +import { defineStore } from 'pinia' + +const useStore = defineStore('store', { + state: () => ({ + someData: 'Hello Pinia' + }) +}) +``` + +您可以访问 `$persist`: + +```ts +const store = useStore() + +store.$persist() +``` + +这将强制将存储状态保留在配置的存储中。 + +> [!WARNING] +> 在大多数情况下,您应该不需要手动合并状态。确保你知道你在做什么,并且你使用 `$persist` 的原因不是由于一个错误(无论是你的实现还是插件本身)。 diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md new file mode 100644 index 0000000..01eedd1 --- /dev/null +++ b/docs/zh/guide/config.md @@ -0,0 +1,250 @@ +# 配置 + +该插件预配置了以下内容: + +- [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) 作为存储。 +- [`store.$id`](https://pinia.vuejs.org/api/interfaces/pinia.StoreProperties.html) 作为存储的默认 key。 +- [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)/[`destr`](https://github.com/unjs/destr) 作为序列化器/反序列化器。 +- 整个状态将持久化到存储中。 + +> [!WARNING] 使用 NUXT ? +> 默认值与 Nuxt 模块不同,以提供 SSR 友好的体验。前往 [Nuxt 使用文档](/frameworks/nuxt)了解更多信息。 + +您可以向存储的`persist`属性传递一个对象来配置持久性。 + +::: code-group +```ts [setup syntax] +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export const useStore = defineStore('main', () => { + const someState = ref('hello pinia') + return { someState } +}, { + persist: { + // CONFIG OPTIONS HERE + } +}) +``` +```ts [option syntax] +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + // CONFIG OPTIONS HERE + }, +}) +``` +::: + +## key + +- **类型**: `string` +- **默认值**: `store.$id` + +用于引用存储中存储的反序列化数据的 Key。 + +:::details Example +```ts{8} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + key: 'my-custom-key', + }, +}) +``` + +此存储将在`localStorage`中的`my-custom-key`项下持久化。 +::: + +## storage + +- **类型**: [`StorageLike`](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts#L8) +- **默认值**: [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) + +将数据保存到 Storage 中。 必须有 `getItem: (key: string) => string | null` 和 `setItem: (key: string, value: string) => void` 方法。 + +:::details Example +```ts{8} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + storage: sessionStorage, + }, +}) +``` + +此存储将保留在 [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)中。 +::: + +> [!WARNING] +> 存储必须是同步的。更多信息请见 [限制页面](/guide/limitations.html#storage-must-be-synchronous)。 + +## serializer + +- **类型**: [`Serializer`](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/src/types.ts#L23) +- **默认值**: [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify)/[`destr`](https://github.com/unjs/destr) + +自定义序列化程序,用于在持久化之前序列化数据,并在解除冻结存储之前反序列化数据。 必须有 `serialize: (value: StateTree) => string` 和 `deserialize: (value: string) => StateTree` 方法。 + +:::details Example +```ts{9-11} +import { defineStore } from 'pinia' +import { parse, stringify } from 'zipson' + +export const useStore = defineStore('store', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + serializer: { + deserialize: parse, + serialize: stringify + } + }, +}) +``` + +此存储将使用 [`zipson`](https://jgranstrom.github.io/zipson/)的 `stringify`/`parse` 来处理序列化/反序列化,并添加了压缩。 +::: + +## pick + +- **类型**: `string[] | Path[]` +- **默认值**: `undefined` + +用于选择应持久化的内容的点表示法路径数组 `[]` 表示不持久化任何状态, `undefined` 表示持久化整个状态。 + +:::details Example +```ts{12} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + save: { + me: 'saved', + notMe: 'not-saved', + }, + saveMeToo: 'saved', + }), + persist: { + pick: ['save.me', 'saveMeToo'], + }, +}) +``` + +在此存储中,将保留 `save.me` 和 `saveMeToo` 。 `save.notMe` 不会持久化。 +::: + +> [!TIP] +> 状态推断类型的自动补全可以帮助您选择哪些路径。 + +## omit + +- **类型**: `string[] | Path[]` +- **默认值**: `undefined` + +要从应持久化的内容中省略的点表示法路径数组。 `[]` 或 `undefined` 表示整个状态持续存在(不遗漏任何内容)。 + +:::details Example +```ts{12} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + ignore: { + me: 'not-saved', + notMe: 'saved', + }, + ignoreMeToo: 'not-saved', + }), + persist: { + omit: ['ignore.me', 'ignoreMeToo'], + }, +}) +``` + +在这个存储中,只有 `ignore.notMe` 值将被持久化。`ignore.me` 和 `ignoreMeToo` 不会被保留。 +::: + +> [!TIP] +> 状态推断类型的自动补全可以帮助您确定可以省略哪些路径。 + +## beforeHydrate + +- **类型**: `(context: PiniaPluginContext) => void` +- **默认值**: `undefined` + +钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 + +:::details Example +```ts{8-9} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + beforeHydrate: (ctx) => { + console.log(`about to hydrate '${ctx.store.$id}'`) + } + }, +}) +``` + +此存储将在rehydrated `about to hydrate 'store'` _之前_ 进行记录。 +::: + +> [!WARNING] +> 当心与 `PiniaPluginContext` 交互,可能会发生意外行为。 + +## afterHydrate + +- **类型**: `(context: PiniaPluginContext) => void` +- **默认值**: `undefined` + +钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 + +:::details Example +```ts{8-9} twoslash +import { defineStore } from 'pinia' + +export const useStore = defineStore('store', { + state: () => ({ + someState: 'hello pinia', + }), + persist: { + afterHydrate: (ctx) => { + console.log(`just hydrated '${ctx.store.$id}'`) + } + }, +}) +``` + +此存储将在rehydrated `about to hydrate 'store'` _之前_ 进行记录。 +::: + +> [!WARNING] +> 当心与 `PiniaPluginContext` 交互,可能会发生意外行为。 + +## debug + +- **类型**: `boolean` +- **默认值**: `false` + +如果设置为 true,则在 persisting/hydrating stores 时可能发生的任何错误都将记录为 `console.error`。 + +> [!WARNING] +> 不进行环境检查: 如果启用此选项,生产中也会记录错误。 diff --git a/docs/zh/guide/index.md b/docs/zh/guide/index.md new file mode 100644 index 0000000..b4f1e30 --- /dev/null +++ b/docs/zh/guide/index.md @@ -0,0 +1,74 @@ +# 开始 + +## 概述 + +此插件与 `pinia>=2.0.0` 兼容, 请确保在继续之前 [已安装 Pinia](https://pinia.vuejs.org/getting-started.html) 。 `pinia-plugin-persistedstate` 具有许多功能,使 Pinia store 的持久化变得轻松且可配置: + +- 一个类似于 [`vuex-persistedstate`](https://github.com/robinvdvleuten/vuex-persistedstate)的 API。 +- Per-store 配置. +- 自定义存储和自定义数据序列化程序。 +- Pre/post persistence/hydration hooks. +- 每个store有多个配置。 + +> [!TIP] 使用 NUXT ? +> 此包导出一个模块,以便更好地与 Nuxt 集成和开箱即用的 SSR 支持。在其[文档](/frameworks/nuxt)中了解更多信息。 + +## 安装 + +1. 用您喜欢的软件包管理器安装依赖项: + ::: code-group + ```sh [pnpm] + pnpm add pinia-plugin-persistedstate + ``` + ```sh [npm] + npm i pinia-plugin-persistedstate + ``` + ```sh [yarn] + yarn add pinia-plugin-persistedstate + ``` + ::: + +2. 将插件添加到你的 pinia 实例中: +```ts +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +const pinia = createPinia() +pinia.use(piniaPluginPersistedstate) +``` + +## 用法 + +在声明您的store时,请将新`persist`选项设置为 `true`。 + +::: code-group +```ts{11} [setup syntax] +import { defineStore } from 'pinia' +import { ref } from 'vue' + +export const useStore = defineStore( + 'main', + () => { + const someState = ref('hello pinia') + return { someState } + }, + { + persist: true, + }, +) +``` +```ts{9} [option syntax] +import { defineStore } from 'pinia' + +export const useStore = defineStore('main', { + state: () => { + return { + someState: 'hello pinia', + } + }, + persist: true, +}) +``` +::: + +您的整个 store 现在将使用 [默认的持久性设置](/guide/config)进行保存。 diff --git a/docs/zh/guide/limitations.md b/docs/zh/guide/limitations.md new file mode 100644 index 0000000..ce81bc6 --- /dev/null +++ b/docs/zh/guide/limitations.md @@ -0,0 +1,52 @@ +# 局限性 + +虽然该插件提供了许多灵活性和功能,但也应考虑一些限制。 + +## Storage 必须是同步的 + +在提供自定义[`storage`](/guide/config#storage)时,其方法必须是同步的。这是因为 Pinia 的状态订阅 ([`$subscribe`](https://pinia.vuejs.org/core-concepts/state#Subscribing-to-the-state)) 是同步的。 + + +:::tip Workaround +要添加异步行为(例如使用异步存储),您可以尝试 [订阅操作 (`$onAction`)](https://pinia.vuejs.org/core-concepts/actions.html#Subscribing-to-actions). +::: + +## 引用不持久化 + +由于序列化过程,引用在刷新时丢失。 +请考虑以下事项: + +```ts +const a = { + 1: 'one', + 2: 'two', + // ... +} +const b = a +``` + +在序列化之前,`a` 和 `b` 指向同一个对象: +```ts +a === b // -> true +``` + +在反序列化之后,`a` 和 `b` 是具有相同内容的两个不同的对象: +```ts +a === b // -> false +``` + +因此,`a` 和 `b` 之间的响应式丧失。 + +:::tip Workaround +要解决这个问题,您可以从持久化中排除 `a` 或 `b` (使用[`pick`](/guide/config#pick)选项)并使用[` afterHydrate `](/guide/config#afterhydrate)钩子在hydration后重新填充它们。这样, `a` 和 `b` 再次具有相同的参照,响应式恢复。 +::: + +## 非基本数据类型不持久化 + +由于序列化过程,诸如 `Date` 之类的非基本数据类型不会被再rehydrated为 `Date` 对象,而是被再水合为 `string` 。 + +:::tip Workaround +要解决此问题,您可以: +- 使用 [`afterHydrate`](/guide/config#afterhydrate) 钩子在rehydration后重新创建对象。 +- 使用支持要保持的数据类型 [`serializer`](/guide/config#serializer) 。 +::: diff --git a/docs/zh/guide/why.md b/docs/zh/guide/why.md new file mode 100644 index 0000000..52ac0e6 --- /dev/null +++ b/docs/zh/guide/why.md @@ -0,0 +1,24 @@ +# 为什么使用这个插件? + +这个插件诞生于 Pinia 的早期,在它正式取代 [VueX](https://vuex.vuejs.org/)之前。它最初的目标是为 Pinia 重现 [vuex-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate) 。 + +## 我需要一个插件来持久化我的stores吗? + +简短的回答:“没有”。有很多解决方案可以将数据存储在`localStorage`中,例如甚至不需要向 Pinia 注入插件。下面是一个[VueUse](https://vueuse.org/)使用`useLocalStorage`的示例: + +```ts +import { useLocalStorage } from '@vueuse/core' +import { defineStore } from 'pinia' + +defineStore('store', () => { + const someState = useLocalStorage('stored-state', 'initialValue') + + return { someState } +}) +``` + +## 为什么我需要这个插件? + +该插件 `pinia-plugin-persistedstate`旨在通过一致的 API 为每个人和每个项目提供对 Pinia store 的持久化。无论你是习惯使用默认值来保存一个完整的 store,还是需要具有多个 storage 和一个自定义序列化器的细粒度配置,该插件都能帮你搞定,所有这些都在您想要持久化的存储上的同一个`persist`选项中。 + +这个插件是积极维护的,为您带来更好的持久化stores的开发者体验。如果您有任何问题、遇到错误或想要提出新功能,非常欢迎您在 [GitHub 仓库](https://github.com/prazdevs/pinia-plugin-persistedstate) 中 [做出贡献](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/CONTRIBUTING.md). From 24b353d77d32be89e9bd96b47f07f179f4fa2a3f Mon Sep 17 00:00:00 2001 From: lichong <1546214265@qq.com> Date: Thu, 26 Sep 2024 09:48:32 +0800 Subject: [PATCH 2/4] Translate Chinese --- docs/zh/index.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/zh/index.md diff --git a/docs/zh/index.md b/docs/zh/index.md new file mode 100644 index 0000000..5f46b2a --- /dev/null +++ b/docs/zh/index.md @@ -0,0 +1,38 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "Pinia 插件 Persistedstate" + text: "可配置的 Pinia 存储持久化" + tagline: 用友好的API存储. + actions: + - theme: brand + text: 开始使用 + link: /guide/ + - theme: alt + text: 在GitHub上查看 + link: https://github.com/prazdevs/pinia-plugin-persistedstate + image: + light: /logo-light.svg + dark: /logo-dark.svg + alt: Pinia Plugin Persistedstate + +features: + - title: 友好的 API + details: 受 vuex-persistedstate 启发的友好 API 持久化商店。 + icon: + - title: 高度可定制化 + details: 自定义存储 / 序列化器和路径选取 / 等等。 + link: /guide/config + linkText: 配置选项 + icon: + - title: Nuxt 支持 + details: 对带有 cookie 的 Nuxt 的开箱即用 SSR 支持。 + link: /nuxt + linkText: 与 Nuxt 一起使用 + icon: + - title: 更轻盈 + icon: + details: 最小压缩小于 2kB。 +--- From a9ed054f8b3fa32a61b8a2349c0b8952ea7bc883 Mon Sep 17 00:00:00 2001 From: lichong <1546214265@qq.com> Date: Thu, 26 Sep 2024 10:26:32 +0800 Subject: [PATCH 3/4] Translate Chinese --- docs/.vitepress/config/zh.ts | 22 +++++++++++++++++++--- docs/zh/frameworks/nuxt.md | 12 ++++++------ docs/zh/frameworks/others.md | 4 ++-- docs/zh/guide/advanced.md | 8 ++++---- docs/zh/guide/config.md | 32 ++++++++++++++++---------------- docs/zh/index.md | 8 ++++---- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/docs/.vitepress/config/zh.ts b/docs/.vitepress/config/zh.ts index 485a651..2e5f00d 100644 --- a/docs/.vitepress/config/zh.ts +++ b/docs/.vitepress/config/zh.ts @@ -8,6 +8,22 @@ export const zh: LocaleSpecificConfig = { text: '建议对此页面进行更改', pattern: 'https://github.com/prazdevs/pinia-plugin-persistedstate/edit/main/docs/:path', }, + docFooter: { + prev: '上一页', + next: '下一页', + }, + + outline: { + label: '页面导航', + }, + + lastUpdated: { + text: '最后更新于', + formatOptions: { + dateStyle: 'short', + timeStyle: 'medium', + }, + }, nav: [ { text: '指南', @@ -69,13 +85,13 @@ export const zh: LocaleSpecificConfig = { { text: '框架', items: [ - { text: 'Nuxt', link: '/frameworks/nuxt' }, - { text: '其他框架', link: '/frameworks/others' }, + { text: 'Nuxt', link: '/zh/frameworks/nuxt' }, + { text: '其他框架', link: '/zh/frameworks/others' }, ], }, ], footer: { - message: '在 MIT 许可证下发布。', + message: '基于 MIT 许可发布。', copyright: '版权所有 © 2021 年至今 Sacha Bouillez 及贡献者', }, diff --git a/docs/zh/frameworks/nuxt.md b/docs/zh/frameworks/nuxt.md index f127832..793d560 100644 --- a/docs/zh/frameworks/nuxt.md +++ b/docs/zh/frameworks/nuxt.md @@ -1,4 +1,4 @@ -# Usage with Nuxt +# 在 Nuxt 中使用 该软件包 `pinia-plugin-persistedstate` 附带一个 Nuxt 模块,可提供开箱即用的 SSR 友好体验。 @@ -74,7 +74,7 @@ Nuxt 模块预配置了以下内容: 您可以通过使用自动导入的 `piniaPluginPersistedstate` 变量下的可用存储来配置要使用的存储。 -> [!WARNING] +> [!WARNING] 警告 > 使用 `persistedState` 公开的存储之外的其他存储可能会出现意外行为。 ### `cookies` @@ -94,7 +94,7 @@ export const useStore = defineStore('main', { }) ``` -> [!TIP] +> [!TIP] 提示 > `persistedState.Cookies` 方法接受一个对象参数来配置带有以下选项的cookie(从Nuxt的 `useCookie` 继承而来): > - [`domain`](https://nuxt.com/docs/api/composables/use-cookie#domain) > - [`expires`](https://nuxt.com/docs/api/composables/use-cookie#maxage-expires) @@ -122,7 +122,7 @@ export const useStore = defineStore('main', { }) ``` -> [!WARNING] +> [!WARNING] 警告 > `localStorage` 仅限客户端。 ### `sessionStorage` @@ -142,10 +142,10 @@ export const useStore = defineStore('main', { }) ``` -> [!WARNING] +> [!WARNING] 警告 > `sessionStorage` 仅限客户端。 -## Global options +## 全局选项 该模块接受在 `piniaPluginPersistedstate` key下的 `nuxt.config.ts` 中定义的一些选项: diff --git a/docs/zh/frameworks/others.md b/docs/zh/frameworks/others.md index 29d128f..ab5241c 100644 --- a/docs/zh/frameworks/others.md +++ b/docs/zh/frameworks/others.md @@ -2,5 +2,5 @@ 没有计划在 Nuxt 之外为 Vue 框架提供官方支持。但是,该插件应该可以在大多数框架中使用,就像任何 Pinia 插件一样。请注意潜在的 SSR 警告。 -> [!IMPORTANT] -> 如果你想提供在Quasar、Ionic或Vike等框架中集成“pinia-plugin-persistedstate”的食谱,非常欢迎你 [为文档做出贡献](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/CONTRIBUTING.md)! +> [!IMPORTANT] 重要 +> 如果你想提供在Quasar、Ionic或Vike等框架中集成 `pinia-plugin-persistedstate` 的配置,非常欢迎你 [为文档做出贡献](https://github.com/prazdevs/pinia-plugin-persistedstate/blob/main/CONTRIBUTING.md)! diff --git a/docs/zh/guide/advanced.md b/docs/zh/guide/advanced.md index 60760ed..69614a8 100644 --- a/docs/zh/guide/advanced.md +++ b/docs/zh/guide/advanced.md @@ -27,7 +27,7 @@ pinia.use(createPersistedState({ 传递给存储的 `persist` 配置的任何选项都将覆盖在全局选项中声明的对应选项。 > [!WARNING] 使用 NUXT ? -> Nuxt 模块中的全局选项作为模块选项处理,与独立的插件全局选项不同。在 [Nuxt 模块文档 ](/frameworks/nuxt)中阅读更多内容。 +> Nuxt 模块中的全局选项作为模块选项处理,与独立的插件全局选项不同。在 [Nuxt 模块文档 ](/frameworks/nuxt)中阅读更多内容。 ## 全局密钥选项 @@ -136,10 +136,10 @@ store.$hydrate({ runHooks: false }) 这将从存储中获取数据并用它替换当前状态。在上面的例子中,钩子不会被触发。 -> [!WARNING] +> [!WARNING] 警告 > 在大多数情况下,您应该不需要手动合并状态。确保你知道你在做什么,并且你使用 `$hydrate` 的原因不是由于一个错误(无论是你的实现还是插件本身)。 -## Forcing the persistence +## 强制持久化 如果您需要手动触发存储的持久性,现在每个存储都公开了一个 `$persist` 方法。 @@ -165,5 +165,5 @@ store.$persist() 这将强制将存储状态保留在配置的存储中。 -> [!WARNING] +> [!WARNING] 警告 > 在大多数情况下,您应该不需要手动合并状态。确保你知道你在做什么,并且你使用 `$persist` 的原因不是由于一个错误(无论是你的实现还是插件本身)。 diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index 01eedd1..7275378 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -47,7 +47,7 @@ export const useStore = defineStore('main', { 用于引用存储中存储的反序列化数据的 Key。 -:::details Example +:::details 例子 ```ts{8} twoslash import { defineStore } from 'pinia' @@ -71,7 +71,7 @@ export const useStore = defineStore('store', { 将数据保存到 Storage 中。 必须有 `getItem: (key: string) => string | null` 和 `setItem: (key: string, value: string) => void` 方法。 -:::details Example +:::details 例子 ```ts{8} twoslash import { defineStore } from 'pinia' @@ -88,7 +88,7 @@ export const useStore = defineStore('store', { 此存储将保留在 [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)中。 ::: -> [!WARNING] +> [!WARNING] 警告 > 存储必须是同步的。更多信息请见 [限制页面](/guide/limitations.html#storage-must-be-synchronous)。 ## serializer @@ -98,7 +98,7 @@ export const useStore = defineStore('store', { 自定义序列化程序,用于在持久化之前序列化数据,并在解除冻结存储之前反序列化数据。 必须有 `serialize: (value: StateTree) => string` 和 `deserialize: (value: string) => StateTree` 方法。 -:::details Example +:::details 例子 ```ts{9-11} import { defineStore } from 'pinia' import { parse, stringify } from 'zipson' @@ -126,7 +126,7 @@ export const useStore = defineStore('store', { 用于选择应持久化的内容的点表示法路径数组 `[]` 表示不持久化任何状态, `undefined` 表示持久化整个状态。 -:::details Example +:::details 例子 ```ts{12} twoslash import { defineStore } from 'pinia' @@ -147,7 +147,7 @@ export const useStore = defineStore('store', { 在此存储中,将保留 `save.me` 和 `saveMeToo` 。 `save.notMe` 不会持久化。 ::: -> [!TIP] +> [!TIP] 提示 > 状态推断类型的自动补全可以帮助您选择哪些路径。 ## omit @@ -157,7 +157,7 @@ export const useStore = defineStore('store', { 要从应持久化的内容中省略的点表示法路径数组。 `[]` 或 `undefined` 表示整个状态持续存在(不遗漏任何内容)。 -:::details Example +:::details 例子 ```ts{12} twoslash import { defineStore } from 'pinia' @@ -178,7 +178,7 @@ export const useStore = defineStore('store', { 在这个存储中,只有 `ignore.notMe` 值将被持久化。`ignore.me` 和 `ignoreMeToo` 不会被保留。 ::: -> [!TIP] +> [!TIP] 提示 > 状态推断类型的自动补全可以帮助您确定可以省略哪些路径。 ## beforeHydrate @@ -186,9 +186,9 @@ export const useStore = defineStore('store', { - **类型**: `(context: PiniaPluginContext) => void` - **默认值**: `undefined` -钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 +钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 -:::details Example +:::details 例子 ```ts{8-9} twoslash import { defineStore } from 'pinia' @@ -207,17 +207,17 @@ export const useStore = defineStore('store', { 此存储将在rehydrated `about to hydrate 'store'` _之前_ 进行记录。 ::: -> [!WARNING] -> 当心与 `PiniaPluginContext` 交互,可能会发生意外行为。 +> [!WARNING] 警告 +> 当心与 `PiniaPluginContext` 交互,可能会发生意外行为。 ## afterHydrate - **类型**: `(context: PiniaPluginContext) => void` - **默认值**: `undefined` -钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 +钩子函数在用持久化数据激活 store state 之前运行。这个钩子可以访问整个 [`PiniaPluginContext`](https://pinia.vuejs.org/api/pinia/interfaces/PiniaPluginContext.html)。 这可以用来在hydration作用之前执行特定的操作。 -:::details Example +:::details 例子 ```ts{8-9} twoslash import { defineStore } from 'pinia' @@ -236,7 +236,7 @@ export const useStore = defineStore('store', { 此存储将在rehydrated `about to hydrate 'store'` _之前_ 进行记录。 ::: -> [!WARNING] +> [!WARNING] 警告 > 当心与 `PiniaPluginContext` 交互,可能会发生意外行为。 ## debug @@ -246,5 +246,5 @@ export const useStore = defineStore('store', { 如果设置为 true,则在 persisting/hydrating stores 时可能发生的任何错误都将记录为 `console.error`。 -> [!WARNING] +> [!WARNING] 警告 > 不进行环境检查: 如果启用此选项,生产中也会记录错误。 diff --git a/docs/zh/index.md b/docs/zh/index.md index 5f46b2a..9e99613 100644 --- a/docs/zh/index.md +++ b/docs/zh/index.md @@ -9,7 +9,7 @@ hero: actions: - theme: brand text: 开始使用 - link: /guide/ + link: /zh/guide/ - theme: alt text: 在GitHub上查看 link: https://github.com/prazdevs/pinia-plugin-persistedstate @@ -24,13 +24,13 @@ features: icon: - title: 高度可定制化 details: 自定义存储 / 序列化器和路径选取 / 等等。 - link: /guide/config + link: /zh/guide/config linkText: 配置选项 icon: - title: Nuxt 支持 details: 对带有 cookie 的 Nuxt 的开箱即用 SSR 支持。 - link: /nuxt - linkText: 与 Nuxt 一起使用 + link: /zh/nuxt + linkText: 在 Nuxt 中使用 icon: - title: 更轻盈 icon: From c3370c66aec3110d362a19debd581133b68e7844 Mon Sep 17 00:00:00 2001 From: lichong <1546214265@qq.com> Date: Tue, 8 Oct 2024 11:39:40 +0800 Subject: [PATCH 4/4] Warning repair --- docs/.vitepress/config/index.ts | 2 +- docs/zh/guide/limitations.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/.vitepress/config/index.ts b/docs/.vitepress/config/index.ts index 5d791e0..5544b4d 100644 --- a/docs/.vitepress/config/index.ts +++ b/docs/.vitepress/config/index.ts @@ -72,6 +72,6 @@ export default defineConfig({ lang: 'en', ...en, }, - zh: { label: '简体中文', ...zh } + zh: { label: '简体中文', ...zh }, }, }) diff --git a/docs/zh/guide/limitations.md b/docs/zh/guide/limitations.md index ce81bc6..d27a742 100644 --- a/docs/zh/guide/limitations.md +++ b/docs/zh/guide/limitations.md @@ -6,7 +6,6 @@ 在提供自定义[`storage`](/guide/config#storage)时,其方法必须是同步的。这是因为 Pinia 的状态订阅 ([`$subscribe`](https://pinia.vuejs.org/core-concepts/state#Subscribing-to-the-state)) 是同步的。 - :::tip Workaround 要添加异步行为(例如使用异步存储),您可以尝试 [订阅操作 (`$onAction`)](https://pinia.vuejs.org/core-concepts/actions.html#Subscribing-to-actions). :::