From: Xavi Lee Date: Tue, 25 Oct 2022 16:04:07 +0000 (+0800) Subject: docs(zh): Polish the Simplified Chinese translations (Part 1) (#1733) X-Git-Tag: @pinia/nuxt@0.4.4~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a9fbe33f93d806688603200eb0ae14270e67e860;p=thirdparty%2Fvuejs%2Fpinia.git docs(zh): Polish the Simplified Chinese translations (Part 1) (#1733) Co-authored-by: KimYangOfCat --- diff --git a/packages/docs/.vitepress/locales/zh.js b/packages/docs/.vitepress/locales/zh.js index 5e337c4b..4ecd2acd 100644 --- a/packages/docs/.vitepress/locales/zh.js +++ b/packages/docs/.vitepress/locales/zh.js @@ -69,7 +69,7 @@ export default { { text: '核心概念', children: [ - { text: '定义一个 Store', link: '/zh/core-concepts/' }, + { text: '定义 Store', link: '/zh/core-concepts/' }, { text: 'State', link: '/zh/core-concepts/state.html' }, { text: 'Getter', link: '/zh/core-concepts/getters.html' }, { text: 'Action', link: '/zh/core-concepts/actions.html' }, diff --git a/packages/docs/zh/api/interfaces/pinia.DefineStoreOptions.md b/packages/docs/zh/api/interfaces/pinia.DefineStoreOptions.md index 5692829e..e084f7dc 100644 --- a/packages/docs/zh/api/interfaces/pinia.DefineStoreOptions.md +++ b/packages/docs/zh/api/interfaces/pinia.DefineStoreOptions.md @@ -54,7 +54,7 @@ ___ • **id**: `Id` -唯一的字符串密钥,用于识别整个应用程序中的 store。 +唯一的字符串密钥,用于识别整个应用中的 store。 ___ @@ -67,7 +67,7 @@ ___ ▸ (): `S` 创建一个新 state 的函数。 -**必须是一个箭头函数**,以确保正确的类型检查! +**必须是一个箭头函数**,以确保正确的类型标注! ##### 返回值 {#returns} @@ -79,13 +79,13 @@ ___ ▸ `Optional` **hydrate**(`storeState`, `initialState`): `void` -当 store 定义中使用了复杂的 state(如仅客户端的引用),并且仅从 `pinia.state` 中复制值是不够时, +当 store 定义中使用了复杂的 state (如仅客户端的引用),并且仅从 `pinia.state` 中复制值是不够时, 允许在 SSR 期间对 store 进行 hydrating。 **`Example`** 如果在你的 `state` 中,你使用了任何在服务器和客户端有不同值的 `customRef`、`computed` 或 `ref`, -你需要手动对它们进行 hydrate。 +你需要手动激活它们。 例如,一个存储在本地存储的自定义 ref: ```ts diff --git a/packages/docs/zh/api/interfaces/pinia.DefineStoreOptionsInPlugin.md b/packages/docs/zh/api/interfaces/pinia.DefineStoreOptionsInPlugin.md index ebcf45b3..67c0fe69 100644 --- a/packages/docs/zh/api/interfaces/pinia.DefineStoreOptionsInPlugin.md +++ b/packages/docs/zh/api/interfaces/pinia.DefineStoreOptionsInPlugin.md @@ -60,7 +60,7 @@ ___ ▸ (): `S` 创建一个新 state 的函数。 -**必须是一个箭头函数**,以确保正确的类型检查! +**必须是一个箭头函数**,以确保正确的类型标注! #### 返回值 {#returns} @@ -76,13 +76,13 @@ Omit.state ▸ `Optional` **hydrate**(`storeState`, `initialState`): `void` -当 store 定义中使用了复杂的状态(如仅客户端的引用),并且从 `pinia.state` 中复制值是不够时, +当 store 定义中使用了复杂的 state (如仅客户端的引用),并且从 `pinia.state` 中复制值是不够时, 允许在 SSR 期间对 store 进行 hydrating。 **`Example`** 如果在你的 `state` 中,你使用了任何 `customRef`,任何 `computed`,或任何在服务器和客户端有不同值的 `ref`, -你需要手动对它们进行 hydrate。 +你需要手动激活它们。 例如,一个存储在本地存储的自定义 ref: ```ts diff --git a/packages/docs/zh/api/interfaces/pinia.MapStoresCustomization.md b/packages/docs/zh/api/interfaces/pinia.MapStoresCustomization.md index 13fd2793..b168066c 100644 --- a/packages/docs/zh/api/interfaces/pinia.MapStoresCustomization.md +++ b/packages/docs/zh/api/interfaces/pinia.MapStoresCustomization.md @@ -10,6 +10,6 @@ sidebarDepth: 3 [pinia](../modules/pinia.md).MapStoresCustomization -允许自定义 map helpers 的接口。用以下属性来扩展这个接口: +允许自定义映射辅助函数的接口。用以下属性来扩展这个接口: - `suffix`: 字符串。影响 `mapStores()` 的后缀,默认为`Store`。 diff --git a/packages/docs/zh/api/interfaces/pinia.StoreDefinition.md b/packages/docs/zh/api/interfaces/pinia.StoreDefinition.md index 528d28c5..8e8c298a 100644 --- a/packages/docs/zh/api/interfaces/pinia.StoreDefinition.md +++ b/packages/docs/zh/api/interfaces/pinia.StoreDefinition.md @@ -44,5 +44,5 @@ sidebarDepth: 3 • **$id**: `Id` - store 的 id。供 map helpers 使用。 + store 的 id。供映射辅助函数使用。 \ No newline at end of file diff --git a/packages/docs/zh/api/interfaces/pinia._StoreWithState.md b/packages/docs/zh/api/interfaces/pinia._StoreWithState.md index 33b8d4e4..86b8e69c 100644 --- a/packages/docs/zh/api/interfaces/pinia._StoreWithState.md +++ b/packages/docs/zh/api/interfaces/pinia._StoreWithState.md @@ -100,7 +100,7 @@ ___ ```js store.$onAction(({ after, onError }) => { // 你可以在这里创建所有钩子之间的共享变量, - // 同时设置 watcher 并清理它们。 + // 同时设置侦听器并清理它们。 after((resolvedValue) => { // 可以用来清理副作用 // `resolvedValue` 是 action 返回的值, @@ -123,7 +123,7 @@ store.$onAction(({ after, onError }) => { `fn` -删除 watcher 的函数 +删除侦听器的函数 ▸ (): `void` @@ -146,7 +146,7 @@ store.$onAction(({ after, onError }) => { ```js store.$onAction(({ after, onError }) => { // 你可以在这里创建所有钩子之间的共享变量, - // 同时设置 watcher 并清理它们。 + // 同时设置侦听器并清理它们。 after((resolvedValue) => { // 可以用来清理副作用 // `resolvedValue` 是 action 返回的值, @@ -162,7 +162,7 @@ store.$onAction(({ after, onError }) => { `void` -移除 watcher 的函数 +移除侦听器的函数 ___ @@ -185,7 +185,7 @@ ___ ▸ **$patch**<`F`\>(`stateMutator`): `void` 将多个变更分组到一个函数中。 -当 mutation 对象(如 Sets 或数组)或者应用对象补丁不方便时很有用,例如追加到数组中。 +当 mutation 对象(如 Sets 或数组)或者应用对象补丁不方便时很有用,例如追加到数组中。 传递给 `$patch()` 的函数**必须是同步的**。 #### 类型参数 {#type-parameters} @@ -238,7 +238,7 @@ ___ `fn` -删除 watcher 的函数 +删除侦听器的函数 ▸ (): `void` @@ -250,4 +250,4 @@ ___ `void` -移除 watcher 的函数 +移除侦听器的函数 diff --git a/packages/docs/zh/api/modules/pinia.md b/packages/docs/zh/api/modules/pinia.md index 920e6ce8..5b2018b4 100644 --- a/packages/docs/zh/api/modules/pinia.md +++ b/packages/docs/zh/api/modules/pinia.md @@ -553,7 +553,7 @@ ___ Vue 2 插件,必须安装该插件才能使 pinia 工作。 注意,**如果你使用的是 Nuxt.js,那你不需要这个插件**。请使用 `buildModule` 代替: -https://pinia.vuejs.org/ssr/nuxt.html。 +https://pinia.vuejs.org/zh/ssr/nuxt.html。 **`Example`** @@ -581,7 +581,7 @@ new Vue({ ▸ **acceptHMRUpdate**(`initialUseStore`, `hot`): (`newModule`: `any`) => `any` -创建一个 _accept_ 函数,在 Vite 应用程序中传递给 `import.meta.hot`。 +创建一个 _accept_ 函数,在 Vite 应用中传递给 `import.meta.hot`。 **`Example`** @@ -720,7 +720,7 @@ ___ ▸ **mapActions**<`Id`, `S`, `G`, `A`, `KeyMapper`\>(`useStore`, `keyMapper`): [`_MapActionsObjectReturn`](pinia.md#_mapactionsobjectreturn)<`A`, `KeyMapper`\> 通过生成一个传递到组件的 `methods` 字段的对象, -允许直接使用 store 的 action,而不需要使用组合式 API(`setup()`)。 +允许直接使用 store 的 action,而不需要使用组合式 API(`setup()`)。 该对象的值是 action, 而键是产生的方法名称。 @@ -765,7 +765,7 @@ export default { ▸ **mapActions**<`Id`, `S`, `G`, `A`\>(`useStore`, `keys`): [`_MapActionsReturn`](pinia.md#_mapactionsreturn)<`A`\> 允许直接使用 store 里的 action, -而不是必须使用组合式 API(`setup()`), +而不是必须使用组合式 API(`setup()`), 通过生成一个对象,传递到组件的 `methods` 字段。 **`Example`** @@ -816,7 +816,7 @@ ___ 而键则是产生的计算属性的名称。 另外,你还可以传递一个自定义函数, 该函数将接收 state 的作为其第一个参数。 -注意,虽然它可以通过 `this` 访问组件的实例,但它不会被类型检查。 +注意,虽然它可以通过 `this` 访问组件的实例,但它没有标注类型。 **`Example`** @@ -915,11 +915,11 @@ ___ ▸ **mapState**<`Id`, `S`, `G`, `A`, `KeyMapper`\>(`useStore`, `keyMapper`): [`_MapStateObjectReturn`](pinia.md#_mapstateobjectreturn)<`Id`, `S`, `G`, `A`, `KeyMapper`\> 通过生成一个对象,并传递至组件的 `computed` 字段, -以允许在不使用组合式 API(`setup()`)的情况下使用一个 store 的 state 和 getter。 +以允许在不使用组合式 API(`setup()`)的情况下使用一个 store 的 state 和 getter。 该对象的值是 state 属性/getter, 而键是生成的计算属性名称。 你也可以选择传递一个自定义函数,该函数将接收 store 作为其第一个参数。 -注意,虽然它可以通过 `this` 访问组件实例,但它不会被类型检查。 +注意,虽然它可以通过 `this` 访问组件实例,但它没有标注类型。 **`Example`** @@ -970,7 +970,7 @@ export default { ▸ **mapState**<`Id`, `S`, `G`, `A`, `Keys`\>(`useStore`, `keys`): [`_MapStateReturn`](pinia.md#_mapstatereturn)<`S`, `G`, `Keys`\> 通过生成一个对象,并传递到组件的 `computed` 字段, -允许在不使用组合式 API(`setup()`)的情况下 +允许在不使用组合式 API(`setup()`)的情况下 使用一个 store 的 state 和 getter, **`Example`** @@ -1017,7 +1017,7 @@ ___ ▸ **mapStores**<`Stores`\>(...`stores`): [`_Spread`](pinia.md#_spread)<`Stores`\> 通过生成一个对象,传递到组件的 `computed` 字段 -以允许在不使用组合式 API(`setup()`)的情况下使用 store。 +以允许在不使用组合式 API(`setup()`)的情况下使用 store。 它接受一个 store 定义的列表参数。 **`Example`** @@ -1058,7 +1058,7 @@ ___ ▸ **mapWritableState**<`Id`, `S`, `G`, `A`, `KeyMapper`\>(`useStore`, `keyMapper`): [`_MapWritableStateObjectReturn`](pinia.md#_mapwritablestateobjectreturn)<`S`, `KeyMapper`\> -除了创建的计算属性的 stter,其它与 `mapState()` 相同, +除了创建的计算属性的 setter,其他与 `mapState()` 相同, 所以 state 可以被修改。 与 `mapState()` 不同的是,只有 `state` 属性可以被添加。 @@ -1086,7 +1086,7 @@ ___ ▸ **mapWritableState**<`Id`, `S`, `G`, `A`\>(`useStore`, `keys`): [`_MapWritableStateReturn`](pinia.md#_mapwritablestatereturn)<`S`\> 通过生成一个对象并传递到组件的 `computed` 字段 -以允许在不使用组合式 API(`setup()`)的情况下 +以允许在不使用组合式 API(`setup()`)的情况下 使用来自一个 store 的 state 和 getter,。 #### 类型参数 {#type-parameters} @@ -1154,7 +1154,7 @@ ___ ▸ **skipHydrate**<`T`\>(`obj`): `T` -告诉 Pinia 跳过给定对象的 hydration 过程。当你在 store 中返回一个有状态的对象,但它并不是真正的状态时,(仅)在 setup store 中这是很有用的。 +告诉 Pinia 跳过给定对象的激活过程。当你在 store 中返回一个有状态的对象,但它并不是真正的状态时,(仅)在 setup store 中这是很有用的。 例如,在一个 setup store 中返回一个路由器实例。 #### 类型参数 {#type-parameters} diff --git a/packages/docs/zh/cookbook/composables.md b/packages/docs/zh/cookbook/composables.md index 276e6bdc..20ed80c5 100644 --- a/packages/docs/zh/cookbook/composables.md +++ b/packages/docs/zh/cookbook/composables.md @@ -1,6 +1,6 @@ # 处理组合式函数 {#dealing-with-composables} -[组合式函数](https://vuejs.org/guide/reusability/composables.html#composables)是利用 Vue 组合式 API 来封装和复用有状态逻辑的函数。无论你是自己写,还是使用[外部库](https://vueuse.org/),或者两者兼而有之,你都可以在 pinia store 中充分发挥组合式函数的力量。 +[组合式函数](https://cn.vuejs.org/guide/reusability/composables.html#composables)是利用 Vue 组合式 API 来封装和复用有状态逻辑的函数。无论你是自己写,还是使用[外部库](https://vueuse.org/),或者两者都有,你都可以在 pinia store 中充分发挥组合式函数的力量。 ## Option Stores {#option-stores} @@ -14,12 +14,12 @@ export const useAuthStore = defineStore('auth', { }) ``` -请记住,**你只能返回可写的状态**(例如,一个 `ref()`)。下面是一些可用的组合式函数的示例: +请记住,**你只能返回可写的状态**(例如,一个 `ref()`)。下面是一些可用的组合式函数的示例: - [useLocalStorage](https://vueuse.org/core/useLocalStorage/) - [useAsyncState](https://vueuse.org/core/useAsyncState/) -下面是一些不可在 option store 中使用的组合式函数(但可在 setup store 中使用): +下面是一些不可在 option store 中使用的组合式函数(但可在 setup store 中使用): - [useMediaControls](https://vueuse.org/core/useMediaControls/): exposes functions - [useMemoryInfo](https://vueuse.org/core/useMemory/): exposes readonly data @@ -61,7 +61,7 @@ export const useVideoPlayer = defineStore('video', () => { 当处理[服务端渲染](../ssr/index.md)时,你有一些需要额外注意的内容,以便在 store 中使用组合式函数。 -在 [Option Store](#option-stores) 中,你需要定义一个 `hydrate()` 函数。当 store 在客户端(浏览器)上被实例化的过程中,创建 store 时有一个可用的初始状态时,这个函数就会被调用。我们需要定义这个函数的原因是,在这种情况下,`state()` 是不会被调用的。 +在 [Option Store](#option-stores) 中,你需要定义一个 `hydrate()` 函数。当 store 在客户端(浏览器)上被实例化的过程中,创建 store 时有一个可用的初始状态时,这个函数就会被调用。我们需要定义这个函数的原因是,在这种情况下,`state()` 是不会被调用的。 ```ts import { defineStore, skipHydrate } from 'pinia' @@ -80,7 +80,7 @@ export const useAuthStore = defineStore('auth', { }) ``` -在 [Setup Store](#setup-stores) 中,对于任何不应该从初始状态中接收的 state 属性 你都需要使用一个名为 `skipHydrate()` 的辅助函数。与 option store 不同,setup store 不能直接**跳过调用 `state()`**,所以我们用 `skipHydrate()` 标记那些不能被 hydrated 的属性。请注意,这只适用于可写的响应式属性: +在 [Setup Store](#setup-stores) 中,对于任何不应该从初始状态中接收的 state 属性 你都需要使用一个名为 `skipHydrate()` 的辅助函数。与 option store 不同,setup store 不能直接**跳过调用 `state()`**,所以我们用 `skipHydrate()` 标记那些不能被激活的属性。请注意,这只适用于可写的响应式属性: ```ts import { defineStore, skipHydrate } from 'pinia' diff --git a/packages/docs/zh/cookbook/composing-stores.md b/packages/docs/zh/cookbook/composing-stores.md index 602ad1f0..90c42656 100644 --- a/packages/docs/zh/cookbook/composing-stores.md +++ b/packages/docs/zh/cookbook/composing-stores.md @@ -2,7 +2,7 @@ 组合式 store 是可以相互使用,Pinia 当然也支持它。但有一个规则需要遵循: -如果**两个或更多的 store 相互使用**,它们不可以通过 _getters_ 或 _actions_ 创建一个无限循环。它们也不可以**同时**在它们的 setup 函数中直接互相读取对方的 state: +如果**两个或更多的 store 相互使用**,它们不可以通过 *getters* 或 *actions* 创建一个无限循环。它们也不可以**同时**在它们的 setup 函数中直接互相读取对方的 state: ```js const useX = defineStore('x', () => { @@ -42,9 +42,9 @@ const useY = defineStore('y', () => { ## 嵌套 store {#nested-stores} -注意,如果一个 store 使用另一个 store,你可以直接导入并在 _actions_ 和 _getters_ 中调用 `useStore()` 函数。然后你就可以像在 Vue 组件中那样使用 store。参考[共享 Getter](#shared-getters)和[共享 Action](#shared-actions)。 +注意,如果一个 store 使用另一个 store,你可以直接导入并在 *actions* 和 *getters* 中调用 `useStore()` 函数。然后你就可以像在 Vue 组件中那样使用 store。参考[共享 Getter](#shared-getters) 和[共享 Action](#shared-actions)。 -对于 _setup store_ ,你直接使用 store 函数**顶部**的一个 store: +对于 *setup store* ,你直接使用 store 函数**顶部**的一个 store: ```ts import { useUserStore } from './user' @@ -66,7 +66,7 @@ export const useCartStore = defineStore('cart', () => { ## 共享 Getter {#shared-getters} -你可以直接在一个 _getter_ 中调用 `useOtherStore()`: +你可以直接在一个 *getter* 中调用 `useOtherStore()`: ```js import { defineStore } from 'pinia' @@ -85,7 +85,7 @@ export const useCartStore = defineStore('cart', { ## 共享 Actions {#shared-actions} -_actions_ 也一样: +*actions* 也一样: ```js import { defineStore } from 'pinia' diff --git a/packages/docs/zh/cookbook/hot-module-replacement.md b/packages/docs/zh/cookbook/hot-module-replacement.md index 108efc3a..d838f78c 100644 --- a/packages/docs/zh/cookbook/hot-module-replacement.md +++ b/packages/docs/zh/cookbook/hot-module-replacement.md @@ -2,8 +2,8 @@ Pinia 支持热更新,所以你可以编辑你的 store,并直接在你的应用中与它们互动,而不需要重新加载页面,允许你保持当前的 state、并添加甚至删除 state、action 和 getter。 -目前,只有 [Vite](https://vitejs.dev/) 被官方支持,不过任何实现 `import.meta.hot` 规范的构建工具都应该能正常工作。(例如,[webpack](https://webpack.js.org/api/module-variables/#importmetawebpackhot) 似乎使用的是 `import.meta.webpackHot` 而不是 `import.meta.hot` ) -你需要在任何 store 声明旁边添加这段代码。比方说,你有三个 store:`auth.js`、 `cart.js` 和 `chat.js`, 你必须在每个 **store 声明**后都添加(和调整)这段代码。 +目前,只有 [Vite](https://vitejs.dev/) 被官方支持,不过任何实现 `import.meta.hot` 规范的构建工具都应该能正常工作。(例外的是,[webpack](https://webpack.js.org/api/module-variables/#importmetawebpackhot) 似乎使用的是 `import.meta.webpackHot` 而不是 `import.meta.hot` ) +你只需要在任何 store 声明旁边添加这段代码。比方说,你有三个 store:`auth.js`、 `cart.js` 和 `chat.js`, 你必须在每个 **store 声明**后都添加(和调整)这段代码。 ```js // auth.js diff --git a/packages/docs/zh/cookbook/migration-v1-v2.md b/packages/docs/zh/cookbook/migration-v1-v2.md index 0ce2d429..3f7c3575 100644 --- a/packages/docs/zh/cookbook/migration-v1-v2.md +++ b/packages/docs/zh/cookbook/migration-v1-v2.md @@ -1,6 +1,6 @@ # 从 0.x (v1) 迁移至 v2 {#migrating-from-0-x-v1-to-v2} -从 `2.0.0-rc.4` 版本开始,pinia 同时支持 Vue 2 和 Vue 3! 这意味着,v2 版本的所有更新,将会让 Vue 2 和 Vue 3 的用户都受益。如果你使用的是 Vue 3,这对你来说没有任何改变,因为你已经在使用 rc 版本,你可以查看[发布日志](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHANGELOG.md)来了解所有更新的详细解释。如果你使用的不是 Vue 3,**那这个指南是为你准备的**! +从 `2.0.0-rc.4` 版本开始,pinia 同时支持 Vue 2 和 Vue 3!这意味着,v2 版本的所有更新,将会让 Vue 2 和 Vue 3 的用户都受益。如果你使用的是 Vue 3,这对你来说没有任何改变,因为你已经在使用 rc 版本,你可以查看[发布日志](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHANGELOG.md)来了解所有更新的详细解释。如果你使用的不是 Vue 3,**那这个指南是为你准备的**! ## 弃用 {#deprecations} @@ -16,11 +16,11 @@ yarn add 'pinia@^0.x.x' - `createStore()` 变成 `defineStore()` - 在订阅中,`storeName` 变成 `storeId` -- `PiniaPlugin` 更名为 `PiniaVuePlugin`(Vue 2 的 Pinia 插件) -- `$subscribe()` 不再接受 _boolean_ 作为第二个参数,而是传递一个带有 `detached: true` 的对象。 +- `PiniaPlugin` 更名为 `PiniaVuePlugin`(Vue 2 的 Pinia 插件) +- `$subscribe()` 不再接受 *boolean* 作为第二个参数,而是传递一个带有 `detached: true` 的对象。 - Pinia 插件不再直接接收 store 的 `id`。使用 `store.$id` 代替。 -## 破坏性更新 {#breaking-changes} +## 非兼容性更新 {#breaking-changes} 删除下面这些后,你可以用下面命令升级到 V2 版了: @@ -36,7 +36,7 @@ yarn add 'pinia@^2.x.x' 添加于 [2.0.0-rc.0](https://github.com/vuejs/pinia/blob/v2/packages/pinia/CHANGELOG.md#200-rc0-2021-07-28) -用 `StoreGeneric` 取代 `GenericStore` 类型的全部用法。这是新的通用 store 类型,应该接受任何类型的 store。如果你在写函数时使用 `Store` 类型而不想传递其泛型(例如`Store`),你可以使用 `StoreGeneric`,因为没有泛型的 `Store` 类型会创建一个空的 store 类型: +用 `StoreGeneric` 取代 `GenericStore` 类型的全部用法。这是新的通用 store 类型,应该可以接受任何类型的 store。如果你在写函数时使用 `Store` 类型而不想传递其泛型(例如`Store`),你可以使用 `StoreGeneric`,因为没有泛型的 `Store` 类型会创建一个空的 store 类型: ```diff -function takeAnyStore(store: Store) {} @@ -89,7 +89,7 @@ yarn add @vue/composition-api@latest ## 支持 webpack 4 {#webpack-4-support} -如果你使用的是 webpack 4(Vue CLI 使用的是 webpack 4),你可能会遇到这样的错误: +如果你使用的是 webpack 4(Vue CLI 使用的是 webpack 4),你可能会遇到这样的错误: ``` ERROR Failed to compile with 18 errors @@ -99,7 +99,7 @@ ERROR Failed to compile with 18 errors Can't import the named export 'computed' from non EcmaScript module (only default export is available) ``` -这是由于 dist 文件为支持 Node.js 中的原生 ESM 模块进行的现代化适配。为更好地支持 Node,文件现在使用的扩展名是 `.mjs` 和 `.cjs`。要解决这个问题,你有两种可用的方法: +这是构建文件为支持 Node.js 中的原生 ESM 模块进行的现代化适配。为更好地支持 Node,文件现在使用的扩展名是 `.mjs` 和 `.cjs`。要解决这个问题,你有两种可用的方法: - 如果你使用 Vue CLI 4.x,升级你的依赖。具体修复步骤如下。 - 如果你不可能升级,请将下面的代码添加到你的 `vue.config.js` 中: @@ -175,4 +175,4 @@ yarn add @pinia/nuxt } ``` -[ Nuxt 专署章节](../ssr/nuxt.md)也值得阅读。 +[ Nuxt 专署章节](../ssr/nuxt.md)也值得一读。 diff --git a/packages/docs/zh/cookbook/migration-vuex.md b/packages/docs/zh/cookbook/migration-vuex.md index 7df31722..a4b9a870 100644 --- a/packages/docs/zh/cookbook/migration-vuex.md +++ b/packages/docs/zh/cookbook/migration-vuex.md @@ -10,12 +10,12 @@ Vuex 有一个概念,带有多个模块的单一 store。这些模块可以被命名,甚至可以互相嵌套。 -将这个概念过渡到 Pinia 最简单的方法是,你以前使用的每个模块现在都是一个 _store_。每个 store 都需要一个 `id`,类似于 Vuex 中的命名空间。这意味着每个 store 都有命名空间的设计。嵌套模块也可以成为自己的 store。互相依赖的 store 可以直接导入其他 store。 +将这个概念过渡到 Pinia 最简单的方法是,你以前使用的每个模块现在都是一个 *store*。每个 store 都需要一个 `id`,类似于 Vuex 中的命名空间。这意味着每个 store 都有命名空间的设计。嵌套模块也可以成为自己的 store。互相依赖的 store 可以直接导入其他 store。 你的 Vuex 模块如何重构为 Pinia store,完全取决于你,不过这里有一个示例: ```bash -# Vuex 示例(假设是命名模块)。 +# Vuex 示例(假设是命名模块)。 src └── store ├── index.js # 初始化 Vuex,导入模块 @@ -29,14 +29,14 @@ src # Pinia 示例,注意 ID 与之前的命名模块相匹配 src └── stores - ├── index.js # (可选) 初始化 Pinia,不必导入 store + ├── index.js # (可选) 初始化 Pinia,不必导入 store ├── module1.js # 'module1' id ├── nested-module2.js # 'nested/module2' id ├── nested-module3.js # 'nested/module3' id └── nested.js # 'nested' id ``` -这为 store 创建了一个扁平的结构,但也保留了和之前等价的 `id` 命名方式。如果你在根 store(在 Vuex 的 `store/index.js` 文件中)中有一些 state/getter/action/mutation,你可以创建一个名为 `root` 的 store,来保存它们。 +这为 store 创建了一个扁平的结构,但也保留了和之前等价的 `id` 命名方式。如果你在根 store (在 Vuex 的 `store/index.js` 文件中)中有一些 state/getter/action/mutation,你可以创建一个名为 `root` 的 store,来保存它们。 Pinia 的目录一般被命名为 `stores` 而不是 `store`。这是为了强调 Pinia 可以使用多个 store,而不是 Vuex 的单一 store。 @@ -177,24 +177,24 @@ export const useAuthUserStore = defineStore('auth/user', { 1. 为 store 添加一个必要的 `id`,你可以让它与之前的命名保持相同。 2. 如果 `state` 不是一个函数的话 将它转换为一个函数。 3. 转换 `getters` - 1. 删除任何返回同名 state 的 getters(例如: `firstName: (state) => state.firstName`),这些都不是必需的,因为你可以直接从 store 实例中访问任何状态。 - 2. 如果你需要访问其他的 getter,可通过 `this` 访问它们,而不是第二个参数。记住,如果你使用 `this`,那么你必须使用一个普通函数,而不是一个箭头函数。还要注意的是,由于 TS 的限制,你需要指定一个返回类型,更多细节请阅读[这篇文档](../core-concepts/getters.md#accessing-other-getters) + 1. 删除任何返回同名 state 的 getters(例如: `firstName: (state) => state.firstName`),这些都不是必需的,因为你可以直接从 store 实例中访问任何状态。 + 2. 如果你需要访问其他的 getter,可通过 `this` 访问它们,而不是第二个参数。记住,如果你使用 `this`,而且你不得不使用一个普通函数,而不是一个箭头函数,那么由于 TS 的限制,你需要指定一个返回类型,更多细节请阅读[这篇文档](../core-concepts/getters.md#accessing-other-getters) 3. 如果使用 `rootState` 或 `rootGetters` 参数,可以直接导入其他 store 来替代它们,或者如果它们仍然存在于 Vuex ,则直接从 Vuex 中访问它们。 4. 转换 `actions` - 1. 从每个 action 中删除第一个 `context` 参数。所有的东西都应该从 `this` 中访问。 + 1. 从每个 action 中删除第一个 `context` 参数。所有的东西都应该直接从 `this` 中访问。 2. 如果使用其他 store,要么直接导入,要么与 getters 一样,在 Vuex 上访问。 5. 转换 `mutations` - 1. Mutation 已经弃用了。它们可以被转换为 `action`,或者你可以在你的组件中直接赋值给 store(例如,`userStore.firstName = 'First'`) - 2. 如果转换为 action,删除第一个 `state` 参数,用 `this` 代替任何赋值操作中的 `state`。 - 3. 一个常见的 mutation 是将 state 重置为初始 state。这就是 store 的 `$reset` 方法的内置功能。注意,这个功能只存在于 option stores。 + 1. Mutation 已经被弃用了。它们可以被转换为 `action`,或者你可以在你的组件中直接赋值给 store(例如,`userStore.firstName = 'First'`) + 2. 如果你想将它转换为 action,删除第一个 `state` 参数,用 `this` 代替任何赋值操作中的 `state`。 + 3. 一个常见的 mutation 是将 state 重置为初始 state。而这就是 store 的 `$reset` 方法的内置功能。注意,这个功能只存在于 option stores。 -正如你所看到的,你的大部分代码都可以被重复使用。如果有什么遗漏,类型安全也应该帮助你确定需要修改的地方。 +正如你所看到的,你的大部分代码都可以被重复使用。如果有什么遗漏,类型安全也应该可以帮助你确定需要修改的地方。 ## 组件内的使用 {#usage-inside-components} 现在你的 Vuex 模块已经被转换为 Pinia store,但其他使用该模块的组件或文件也需要更新。 -如果你以前使用的是 Vuex 的 `map` helpers,可以看看[不使用 setup() 的用法指南](./options-api.md),因为这些 helpers 大多都是可以复用。 +如果你以前使用的是 Vuex 的 `map` 辅助函数,可以看看[不使用 setup() 的用法指南](./options-api.md),因为这些辅助函数大多都是可以复用的。 如果你以前使用的是 `useStore`,那么就直接导入新 store 并访问其上的 state。比如说: @@ -242,7 +242,7 @@ export default defineComponent({ ## 组件外的使用 {#usage-outside-components} -只要你注意**不在函数外使用 store**,只更新组件外的用法应该很简单。下面是一个在 Vue Router 导航卫士中使用 store 的例子: +只要你注意**不在函数外使用 store**,单独更新组件外的用法应该很简单。下面是一个在 Vue Router 导航守卫中使用 store 的例子: ```ts // Vuex @@ -270,7 +270,7 @@ router.beforeEach((to, from, next) => { ## Vuex 高级用法 {#advanced-vuex-usage} -如果你的 Vuex store 使用了它所提供的一些更高级的功能,也有一些关于如何在 Pinia 中实现同样效果的指导。其中一些要点已经包含在这个[对比总结](../introduction.md#comparison-with-vuex-3-x-4-x)里了。 +如果你的 Vuex store 使用了它所提供的一些更高级的功能,也有一些关于如何在 Pinia 中实现同样效果的指导。其中一些要点已经包含在这个[对比总结](../introduction.md#comparison-with-vuex-3-x-4-x)里了。 ### 动态模块 {#dynamic-modules} diff --git a/packages/docs/zh/cookbook/options-api.md b/packages/docs/zh/cookbook/options-api.md index 67b58b74..fe380dfd 100644 --- a/packages/docs/zh/cookbook/options-api.md +++ b/packages/docs/zh/cookbook/options-api.md @@ -1,6 +1,6 @@ # 不使用 `setup()` 的用法 {#usage-without-setup} -即使你没有使用组合式 API,也可以使用 Pinia(如果你使用 Vue 2,你仍然需要安装 `@vue/composition-api` 插件)。虽然我们推荐你试着学习一下组合式 API,但对你和你的团队来说可能还不是时候,你可能正在迁移一个应用,或者有其他原因。你可以试试下面几个函数: +即使你没有使用组合式 API,也可以使用 Pinia(如果你使用 Vue 2,你仍然需要安装 `@vue/composition-api` 插件)。虽然我们推荐你试着学习一下组合式 API,但对你和你的团队来说目前可能还不是时候,你可能正在迁移一个应用,或者有其他原因。你可以试试下面几个函数: - [mapStores](#giving-access-to-the-whole-store) - [mapState](../core-concepts/state.md#usage-with-the-options-api) @@ -56,7 +56,7 @@ export const pinia = createPinia() ## TypeScript {#typescript} -默认情况下,所有 map helpers 都支持自动补全,你不需要做任何事情。如果你调用 `setMapStoreSuffix()` 修改了 `"Store"` 的后缀,你还需要在 TS 文件或 `global.d.ts` 文件的某个地方添加它。最方便的地方是你调用 `setMapStoreSuffix()` 的地方: +默认情况下,所有映射辅助函数都支持自动补全,你不需要做任何事情。如果你调用 `setMapStoreSuffix()` 修改了 `"Store"` 的后缀,你还需要在 TS 文件或 `global.d.ts` 文件的某个地方添加它。最方便的地方就是你调用 `setMapStoreSuffix()` 的地方: ```ts import { createPinia, setMapStoreSuffix } from 'pinia' @@ -73,5 +73,5 @@ declare module 'pinia' { ``` :::warning -如果你使用的是 TypeScript 声明文件(如 `global.d.ts`),请确保在文件顶部 `import 'pinia'`,以暴露所有现有类型。 +如果你使用的是 TypeScript 声明文件(如 `global.d.ts`),请确保在文件顶部 `import 'pinia'`,以暴露所有现有类型。 ::: diff --git a/packages/docs/zh/cookbook/testing.md b/packages/docs/zh/cookbook/testing.md index eec16a5c..81bba790 100644 --- a/packages/docs/zh/cookbook/testing.md +++ b/packages/docs/zh/cookbook/testing.md @@ -17,7 +17,7 @@ - [Mocking getters](#mocking-getters) - [Pinia 插件](#pinia-plugins) - [端到端测试](#e2e-tests) - - [对组件单元测试(Vue 2)](#unit-test-components-vue-2) + - [对组件单元测试(Vue 2)](#unit-test-components-vue-2) ## 对 store 进行单元测试 {#unit-testing-a-store} @@ -71,7 +71,7 @@ beforeEach(() => { ## 对组件单元测试 {#unit-testing-components} -这可以通过 `createTestingPinia()` 实现,它会返回一个旨在帮助对组件单元测试的 pinia 实例。 +这可以通过 `createTestingPinia()` 实现,它会返回一个仅用于帮助对组件单元测试的 pinia 实例。 从安装 `@pinia/testing` 开始: @@ -113,7 +113,7 @@ expect(store.someAction).toHaveBeenLastCalledWith() ### 初始 State {#initial-state} -在创建测试 Pinia 时,你可以通过传递一个 `initialState` 对象来设置**所有 store 的初始状态**。这个对象将被 pinia 的测试实例用于创建 store 时 _patch_ store。比方说,你想初始化这个 store 的状态: +在创建测试 Pinia 时,你可以通过传递一个 `initialState` 对象来设置**所有 store 的初始状态**。这个对象将被 pinia 的测试实例用于创建 store 时 *patch* store。比方说,你想初始化这个 store 的状态: ```ts import { defineStore } from 'pinia' @@ -124,7 +124,7 @@ const useCounterStore = defineStore('counter', { }) ``` -由于 store 的名字是 _"counter"_,所以你需要传递相应的对象给 `initialState`: +由于 store 的名字是 *"counter"*,所以你需要传递相应的对象给 `initialState`: ```ts // 在测试中的某处 @@ -146,7 +146,7 @@ store.n // 20 ### 自定义 action 的行为 {#customizing-behavior-of-actions} -除非另有指示,`createTestingPinia` 会存根(stub)出所有的store action。这样可以让你你独立测试你的组件和 store。 +除非另有指示,`createTestingPinia` 会存根 (stub) 出所有的 store action。这样可以让你独立测试你的组件和 store。 如果你想恢复这种行为,并在测试中正常执行 action,请在调用 `createTestingPinia` 时指定 `stubActions: false`: @@ -168,7 +168,7 @@ expect(store.someAction).toHaveBeenCalledTimes(1) ### 指定 createSpy 函数 {#specifying-the-createspy-function} -当使用 Jest,或 vitest 且设置 `globals: true` 时,`createTestingPinia` 会自动使用现有测试框架(`jest.fn` 或 `vitest.fn`)的 spy 函数存根(stub) action。如果你使用的是不同的框架,你需要提供一个 [createSpy](/zh/api/interfaces/pinia_testing.TestingOptions.html#createspy) 选项: +当使用 Jest,或 vitest 且设置 `globals: true` 时,`createTestingPinia` 会自动使用现有测试框架(`jest.fn` 或 `vitest.fn`)的 spy 函数存根 (stub) action。如果你使用的是不同的框架,你需要提供一个 [createSpy](/zh/api/interfaces/pinia_testing.TestingOptions.html#createspy) 选项: ```js import sinon from 'sinon' @@ -231,9 +231,9 @@ const wrapper = mount(Counter, { 对于 pinia,你不需要为端到端测试修改任何代码,这就是端到端测试的含义!也许你想测试 HTTP 请求,但这已经超出了本指南的范围😄。 -## 对组件单元测试(Vue 2) {#unit-test-components-vue-2} +## 对组件单元测试(Vue 2) {#unit-test-components-vue-2} -当你使用的是 [Vue Test Utils 1](https://v1.test-utils.vuejs.org/) 时,请将 Pinia 安装在 `localVue` 上: +当你使用的是 [Vue Test Utils 1](https://v1.test-utils.vuejs.org/zh/) 时,请将 Pinia 安装在 `localVue` 上: ```js import { PiniaVuePlugin } from 'pinia' diff --git a/packages/docs/zh/core-concepts/actions.md b/packages/docs/zh/core-concepts/actions.md index 46dc0a53..3acbb9c3 100644 --- a/packages/docs/zh/core-concepts/actions.md +++ b/packages/docs/zh/core-concepts/actions.md @@ -1,11 +1,11 @@ -# Actions {#actions} +# Action {#actions} -Actions 相当于组件中的 [method](https://v3.vuejs.org/guide/data-methods.html#methods)。它们可以通过 `defineStore()` 中的 `actions` 属性来定义,**并且它们也是定义业务逻辑的完美选择。** +Action 相当于组件中的 [method](https://v3.vuejs.org/guide/data-methods.html#methods)。它们可以通过 `defineStore()` 中的 `actions` 属性来定义,**并且它们也是定义业务逻辑的完美选择。** ```js export const useStore = defineStore('main', { @@ -23,7 +23,7 @@ export const useStore = defineStore('main', { }) ``` -类似 [getter](./getters.md),action 也可通过 `this` 访问**整个 store 实例**,并支持**完整的类型约束(以及自动补全✨)**。**不同的是,`action` 可以是异步的**,你可以在它们里面 `await` 调用任何 API,以及其他 action!下面是一个使用 [Mande](https://github.com/posva/mande) 的例子。请注意,你使用什么库并不重要,只要你得到的是一个`Promise`,你甚至可以使用原生 `fetch` 函数(在浏览器中): +类似 [getter](./getters.md),action 也可通过 `this` 访问**整个 store 实例**,并支持**完整的类型标注(以及自动补全✨)**。**不同的是,`action` 可以是异步的**,你可以在它们里面 `await` 调用任何 API,以及其他 action!下面是一个使用 [Mande](https://github.com/posva/mande) 的例子。请注意,你使用什么库并不重要,只要你得到的是一个`Promise`,你甚至可以(在浏览器中)使用原生 `fetch` 函数: ```js import { mande } from 'mande' @@ -53,7 +53,7 @@ export const useUsers = defineStore('users', { 你也完全可以自由地设置任何你想要的参数以及返回任何结果。当调用 action 时,一切类型也都是可以被自动推断出来的。 -Actions 可以像 methods 一样被调用: +Action 可以像方法一样被调用: ```js export default defineComponent({ @@ -69,7 +69,7 @@ export default defineComponent({ ## 访问其他 store 的 action {#accessing-other-stores-actions} -想要使用另一个 store 的话,那你可以直接在 _action_ 中调用就好了: +想要使用另一个 store 的话,那你直接在 *action* 中调用就好了: ```js import { useAuthStore } from './auth-store' @@ -135,7 +135,7 @@ const useCounterStore = defineStore('counter', { ### 使用 `setup()` {#with-setup} -虽然并不是每个人都会使用组合式 API,但 `setup()` 钩子依旧可以使 Pinia 在选项式 API 中更易使用。并且不需要额外的 map helper 函数! +虽然并不是每个开发者都会使用组合式 API,但 `setup()` 钩子依旧可以使 Pinia 在选项式 API 中更易用。并且不需要额外的映射辅助函数! ```js import { useCounterStore } from '../stores/counter' @@ -157,7 +157,7 @@ export default { ### 不使用 `setup()` {#without-setup} -如果你不喜欢使用组合式 API,你也可以使用 `mapActions()` helper 将 action 属性映射为你组件中的方法。 +如果你不喜欢使用组合式 API,你也可以使用 `mapActions()` 辅助函数将 action 属性映射为你组件中的方法。 ```js import { mapActions } from 'pinia' @@ -176,7 +176,7 @@ export default { ## 订阅 action {#subscribing-to-actions} -你可以通过 `store.$onAction()` 来监测 action 和它们的结果。传递给它的回调函数会在 action 本身之前执行。`after` 表示在 promise 解决之后,允许你在 action 解决后执行一个一个回调函数。同样地,`onError` 允许你在 action 抛出错误或 reject 时执行一个回调函数。这些函数对于追踪运行时错误非常有用,类似于[Vue docs 中的这个提示](https://v3.vuejs.org/guide/tooling/deployment.html#tracking-runtime-errors)。 +你可以通过 `store.$onAction()` 来监听 action 和它们的结果。传递给它的回调函数会在 action 本身之前执行。`after` 表示在 promise 解决之后,允许你在 action 解决后执行一个一个回调函数。同样地,`onError` 允许你在 action 抛出错误或 reject 时执行一个回调函数。这些函数对于追踪运行时错误非常有用,类似于[Vue docs 中的这个提示](https://v3.vuejs.org/guide/tooling/deployment.html#tracking-runtime-errors)。 这里有一个例子,在运行 action 之前以及 action resolve/reject 之后打印日志记录。 @@ -217,7 +217,7 @@ const unsubscribe = someStore.$onAction( unsubscribe() ``` -默认情况下,_action 订阅器_ 会被绑定到添加它们的组件上(如果 store 在组件的 `setup()` 内)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 `true` 作为第二个参数传递给 _action 订阅器_,以便将其从当前组件中剥离(_detach_): +默认情况下,*action 订阅器*会被绑定到添加它们的组件上(如果 store 在组件的 `setup()` 内)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 `true` 作为第二个参数传递给 *action 订阅器*,以便将其从当前组件中分离: ```js export default { diff --git a/packages/docs/zh/core-concepts/getters.md b/packages/docs/zh/core-concepts/getters.md index d5619377..96696b11 100644 --- a/packages/docs/zh/core-concepts/getters.md +++ b/packages/docs/zh/core-concepts/getters.md @@ -1,11 +1,11 @@ -# Getters {#getters} +# Getter {#getters} -Getter 完全等同于 store 的 state 的[计算值](https://v3.vuejs.org/guide/reactivity-computed-watchers.html#computed-values)。可以通过 `defineStore()` 中的 `getters` 属性来定义它们。**推荐**使用箭头函数,并且它将接收 `state` 作为第一个参数: +Getter 完全等同于 store 的 state 的[计算值](https://cn.vuejs.org/guide/essentials/computed.html)。可以通过 `defineStore()` 中的 `getters` 属性来定义它们。**推荐**使用箭头函数,并且它将接收 `state` 作为第一个参数: ```js export const useStore = defineStore('main', { @@ -18,7 +18,7 @@ export const useStore = defineStore('main', { }) ``` -大多数时候,getter 仅依赖 state,不过,有时它们也可能会使用其他 getter。因此,在使用常规函数定义 getter 时,我们可以通过 `this` 访问到**整个 store 实例**,**但(在TypeScript中)必须定义返回类型**。这是为了避免 TypeScript 的已知缺陷,**不过这不影响用箭头函数定义的 getter,也不会影响不使用 `this` 的 getter**。 +大多数时候,getter 仅依赖 state,不过,有时它们也可能会使用其他 getter。因此,即使在使用常规函数定义 getter 时,我们也可以通过 `this` 访问到**整个 store 实例**,**但(在 TypeScript 中)必须定义返回类型**。这是为了避免 TypeScript 的已知缺陷,**不过这不影响用箭头函数定义的 getter,也不会影响不使用 `this` 的 getter**。 ```ts export const useStore = defineStore('main', { @@ -32,7 +32,7 @@ export const useStore = defineStore('main', { }, // 返回类型**必须**明确设置 doublePlusOne(): number { - // 整个 store 的 自动补全和类型检查 ✨ + // 整个 store 的 自动补全和类型标注 ✨ return this.doubleCount + 1 }, }, @@ -59,7 +59,7 @@ export default { ## 访问其他 getter {#accessing-other-getters} -与计算属性一样,你可以组合多个 getter。通过 `this`,你可以访问任何其他 getter。即使你没有使用 TypeScript,你也可以用 [JSDoc](https://jsdoc.app/tags-returns.html) 来让你的 IDE 提示类型。 +与计算属性一样,你也可以组合多个 getter。通过 `this`,你可以访问到其他任何 getter。即使你没有使用 TypeScript,你也可以用 [JSDoc](https://jsdoc.app/tags-returns.html) 来让你的 IDE 提示类型。 ```js export const useStore = defineStore('main', { @@ -69,7 +69,7 @@ export const useStore = defineStore('main', { getters: { // 类型是自动推断出来的,因为我们没有使用 `this` doubleCount: (state) => state.count * 2, - // 这里我们需要自己添加类型(在 JS 中使用 JSDoc) + // 这里我们需要自己添加类型(在 JS 中使用 JSDoc) // 可以用 this 来引用 getter /** * 返回 count 的值乘以 2 加 1 @@ -86,7 +86,7 @@ export const useStore = defineStore('main', { ## 向 getter 传递参数 {#passing-arguments-to-getters} -_Getter_ 只是幕后的**计算**属性,所以不可以向它们传递任何参数。不过,你可以从 _getter_ 返回一个函数,该函数可以接受任意参数: +*Getter* 只是幕后的**计算**属性,所以不可以向它们传递任何参数。不过,你可以从 *getter* 返回一个函数,该函数可以接受任意参数: ```js export const useStore = defineStore('main', { @@ -116,7 +116,7 @@ export default { ``` -请注意,当你这样做时,**getter 将不再被缓存**,它们只是一个被你调用的函数。不过,你可以在 getter 本身中缓存一些结果,虽然这种做法并不常见,但可以证明的是它的性能会更好: +请注意,当你这样做时,**getter 将不再被缓存**,它们只是一个被你调用的函数。不过,你可以在 getter 本身中缓存一些结果,虽然这种做法并不常见,但有证明表明它的性能会更好: ```js export const useStore = defineStore('main', { @@ -131,7 +131,7 @@ export const useStore = defineStore('main', { ## 访问其他 store 的 getter {#accessing-other-stores-getters} -想要使用另一个 store 的 getter 的话,那就直接在 _getter_ 内使用就好: +想要使用另一个 store 的 getter 的话,那就直接在 *getter* 内使用就好: ```js import { useOtherStore } from './other-store' @@ -151,7 +151,7 @@ export const useStore = defineStore('main', { ## 使用 `setup()` 时的用法 {#usage-with-setup} -作为 store 的一个属性,你可以直接访问任何 getter(与 state 属性完全一样): +作为 store 的一个属性,你可以直接访问任何 getter(与 state 属性完全一样): ```js export default { @@ -193,7 +193,7 @@ export const useCounterStore = defineStore('counter', { ### 使用 `setup()` {#with-setup} -虽然并不是每个人都会使用组合式 API,但 `setup()` 钩子依旧可以使 Pinia 在选项式 API 中更易使用。并且不需要额外的 map helper 函数! +虽然并不是每个开发者都会使用组合式 API,但 `setup()` 钩子依旧可以使 Pinia 在选项式 API 中更易用。并且不需要额外的映射辅助函数! ```js import { useCounterStore } from '../stores/counter' @@ -214,7 +214,7 @@ export default { ### 不使用 `setup()` {#without-setup} -你可以使用[前一节的 state](./state.md#options-api)中的 `mapState()` 函数来将其映射为 getters: +你可以使用[前一节的 state](./state.md#options-api) 中的 `mapState()` 函数来将其映射为 getters: ```js import { mapState } from 'pinia' diff --git a/packages/docs/zh/core-concepts/index.md b/packages/docs/zh/core-concepts/index.md index 822056bf..8342f653 100644 --- a/packages/docs/zh/core-concepts/index.md +++ b/packages/docs/zh/core-concepts/index.md @@ -1,4 +1,4 @@ -# 定义一个 Store {#defining-a-store} +# 定义 Store {#defining-a-store} { @@ -58,17 +58,17 @@ export const useCounterStore = defineStore('counter', () => { }) ``` -在 _Setup Stores_ 中: +在 *Setup Store* 中: -- `ref()`s 就是 `state` 属性 -- `computed()`s 就是 `getters` -- `function()`s 就是 `actions` +- `ref()` 就是 `state` 属性 +- `computed()` 就是 `getters` +- `function()` 就是 `actions` -Setup stores 比 [Options Stores](#option-stores) 带来了更多的灵活性,因为你可以在一个 store 内创建 watchers,并自由地使用任何[组合式函数](https://vuejs.org/guide/reusability/composables.html#composables)。然而,请记住,使用组合式函数会让 [SSR](../cookbook/composables.md) 变得更加复杂。 +Setup store 比 [Option Store](#option-stores) 带来了更多的灵活性,因为你可以在一个 store 内创建侦听器,并自由地使用任何[组合式函数](https://cn.vuejs.org/guide/reusability/composables.html#composables)。不过,请记住,使用组合式函数会让 [SSR](../cookbook/composables.md) 变得更加复杂。 ## 你应该选用哪种语法? {#what-syntax-should-i-pick} -和 [Vue 的组合式 API 与选项式 API](https://vuejs.org/guide/introduction.html#which-to-choose) 一样,选择你觉得最舒服的那一个就好。如果你还不确实,可以先试试 [Option Stores](#option-stores)。 +和[在 Vue 中如何选择组合式 API 与选项式 API](https://cn.vuejs.org/guide/introduction.html#which-one-to-choose) 一样,选择你觉得最舒服的那一个就好。如果你还不确定,可以先试试 [Option Store](#option-stores)。 ## 使用 Store {#using-the-store} 虽然我们前面定义了一个 store,但在 `setup()` 调用 `useStore()` 之前,store 实例是不会被创建的: @@ -88,11 +88,11 @@ export default { } ``` -你可以定义任意多的 store,但为了让使用 pinia 的益处最大化(比如允许构建工具自动进行代码分割以及 TypeScript 推断),**你应该在不同的文件中去定义 store**。 +你可以定义任意多的 store,但为了让使用 pinia 的益处最大化(比如允许构建工具自动进行代码分割以及 TypeScript 推断),**你应该在不同的文件中去定义 store**。 -如果你还不会使用 `setup` 组件,[你仍然可以通过 _map helpers_ 来使用 Pinia](../cookbook/options-api.md)。 +如果你还不会使用 `setup` 组件,[你也可以通过**映射辅助函数**来使用 Pinia](../cookbook/options-api.md)。 -一旦 store 被实例化,你可以直接访问在 store 的 `state`、`getters` 和 `actions` 中定义的任何属性。我们将在后续章节继续了解这些细节,目前 autocompletion 将帮助你使用相关属性。 +一旦 store 被实例化,你可以直接访问在 store 的 `state`、`getters` 和 `actions` 中定义的任何属性。我们将在后续章节继续了解这些细节,目前自动补全将帮助你使用相关属性。 请注意,`store` 是一个用 `reactive` 包装的对象,这意味着不需要在 getters 后面写 `.value`,就像 `setup` 中的 `props` 一样,**如果你写了,我们也不能解构它**: @@ -100,7 +100,7 @@ export default { export default defineComponent({ setup() { const store = useCounterStore() - // ❌ 这将无法生效,因为它破坏了响应式 + // ❌ 这将无法生效,因为它破坏了响应性 // 这与从 `props` 中解构是一样的。 const { name, doubleCount } = store @@ -129,7 +129,7 @@ export default defineComponent({ const store = useCounterStore() // `name` and `doubleCount` 都是响应式 refs // 这也将为由插件添加的属性创建 refs - // 同时会跳过任何 action 或非响应式(非 ref/响应式)属性 + // 同时会跳过任何 action 或非响应式(非 ref/响应式)属性 const { name, doubleCount } = storeToRefs(store) // 名为 increment 的 action 可以直接提取 const { increment } = store diff --git a/packages/docs/zh/core-concepts/outside-component-usage.md b/packages/docs/zh/core-concepts/outside-component-usage.md index 6a6da494..1150e6b5 100644 --- a/packages/docs/zh/core-concepts/outside-component-usage.md +++ b/packages/docs/zh/core-concepts/outside-component-usage.md @@ -1,12 +1,12 @@ # 在组件外使用 store {#using-a-store-outside-of-a-component} -Pinia store 依靠 `pinia` 实例在所有调用中共享同一个 store 实例。大多数时候,只需调用你定义的 `useStore()` 函数,非常开箱即用。例如,在 `setup()` 中,你不需要再做任何事情。但在组件之外,情况就有点不同了。 +Pinia store 依靠 `pinia` 实例在所有调用中共享同一个 store 实例。大多数时候,只需调用你定义的 `useStore()` 函数,完全开箱即用。例如,在 `setup()` 中,你不需要再做任何事情。但在组件之外,情况就有点不同了。 实际上,`useStore()` 给你的 `app` 自动注入了 `pinia` 实例。这意味着,如果 `pinia` 实例不能自动注入,你必须手动提供给 `useStore()` 函数。 你可以根据不同的应用,以不同的方式解决这个问题。 ## 单页面应用 {#single-page-applications} -如果你不做任何 SSR(服务器端渲染),在用 `app.use(pinia)` 安装 pinia 插件后,对 `useStore()` 的任何调用都会正常工作: +如果你不做任何 SSR(服务器端渲染),在用 `app.use(pinia)` 安装 pinia 插件后,对 `useStore()` 的任何调用都会正常执行: ```js import { useUserStore } from '@/stores/user' @@ -26,7 +26,7 @@ const userStore = useUserStore() 为确保 pinia 实例被激活,最简单的方法就是将 `useStore()` 的调用放在 pinia 安装后才会执行的函数中。 -让我们来看看这个在 Vue Router 的导航卫士中使用 store 的例子。 +让我们来看看这个在 Vue Router 的导航守卫中使用 store 的例子。 ```js import { createRouter } from 'vue-router' @@ -54,6 +54,6 @@ router.beforeEach((to) => { ## 服务端渲染应用 {#ssr-apps} -当处理服务端渲染时,你将必须把 `pinia` 实例传递给 `useStore()`。这可以防止 pinia 在不同的应用程序实例之间共享全局状态。 +当处理服务端渲染时,你将必须把 `pinia` 实例传递给 `useStore()`。这可以防止 pinia 在不同的应用实例之间共享全局状态。 在[SSR 指南](/ssr/index.md)中有一整节专门讨论这个问题,这里只是一个简短的解释。 diff --git a/packages/docs/zh/core-concepts/plugins.md b/packages/docs/zh/core-concepts/plugins.md index 8ae4976f..8bdbcb0c 100644 --- a/packages/docs/zh/core-concepts/plugins.md +++ b/packages/docs/zh/core-concepts/plugins.md @@ -1,12 +1,12 @@ # Plugins {#plugins} -由于有了底层 API 的支持,Pinia store 现在完全可以被扩展。以下是你可以做的事情的清单: +由于有了底层 API 的支持,Pinia store 现在完全支持扩展。以下是你可以扩展的内容: - 为 store 添加新的属性 - 定义 store 时增加新的选项 - 为 store 增加新的方法 - 包装现有的方法 -- 改变或甚至取消 action +- 改变甚至取消 action - 实现副作用,如[本地存储](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) - **仅**应用插件于特定 store @@ -34,12 +34,12 @@ store.secret // 'the cake is a lie' ## 简介 {#introduction} -Pinia 插件是一个函数,可以选择性地返回要添加到 store 的属性。它接收一个可选参数,即 _context_。 +Pinia 插件是一个函数,可以选择性地返回要添加到 store 的属性。它接收一个可选参数,即 *context*。 ```js export function myPiniaPlugin(context) { context.pinia // 用 `createPinia()` 创建的 pinia。 - context.app // 用 `createApp()` 创建的当前应用程序(仅 Vue 3)。 + context.app // 用 `createApp()` 创建的当前应用(仅 Vue 3)。 context.store // 该插件想扩展的 store context.options // 定义传给 `defineStore()` 的 store 的可选对象。 // ... @@ -52,7 +52,7 @@ export function myPiniaPlugin(context) { pinia.use(myPiniaPlugin) ``` -插件只会应用于**在 `pinia` 传递给应用程序后**创建的 store,否则它们不会生效。 +插件只会应用于**在 `pinia` 传递给应用后**创建的 store,否则它们不会生效。 ## 扩展 Store {#augmenting-a-store} @@ -84,7 +84,7 @@ pinia.use(({ store }) => { }) ``` -值得注意的是,每个 store 都被 [`reactive`](https://v3.vuejs.org/api/basic-reactivity.html#reactive)包装过,所以可以自动解包任何它所包含的 Ref(`ref()`、`computed()`...)。 +值得注意的是,每个 store 都被 [`reactive`](https://cn.vuejs.org/api/reactivity-core.html#reactive)包装过,所以可以自动解包任何它所包含的 Ref(`ref()`、`computed()`...)。 ```js const sharedRef = ref('shared') @@ -104,12 +104,12 @@ pinia.use(({ store }) => { ### 添加新的 state {#adding-new-state} -如果你想给 store 添加新的 state 属性,或者在 hydration 过程中使用的属性,**你必须同时在两个地方添加它**。 +如果你想给 store 添加新的 state 属性,或者在激活过程中使用的属性,**你必须同时在两个地方添加它**。 -- 在 `store` 上,因此你可以用 `store.myState` 访问它。 -- 在 `store.$state` 上,因此它可以在 devtools 中使用,并且,**在 SSR 时被序列化(serialized)**。 +- 在 `store` 上,然后你才可以用 `store.myState` 访问它。 +- 在 `store.$state` 上,然后你才可以在 devtools 中使用它,并且,**在 SSR 时被正确序列化(serialized)**。 -除此之外,你肯定也会使用 `ref()`(或其他响应式 API),以便在不同的读取中共享相同的值: +除此之外,你肯定也会使用 `ref()`(或其他响应式 API),以便在不同的读取中共享相同的值: ```js import { toRef, ref } from 'vue' @@ -127,7 +127,7 @@ pinia.use(({ store }) => { // 我们需要将 ref 从 state 转移到 store // 这样的话,两种方式:store.hasError 和 store.$state.hasError 都可以访问 // 并且共享的是同一个变量 - // 查看 https://vuejs.org/api/reactivity-utilities.html#toref + // 查看 https://cn.vuejs.org/api/reactivity-utilities.html#toref store.hasError = toRef(store.$state, 'hasError') // 在这种情况下,最好不要返回 `hasError` @@ -136,10 +136,10 @@ pinia.use(({ store }) => { }) ``` -需要注意的是,在一个插件中, state 变更或添加(包括调用 `store.$patch()`)都是发生在 store 被激活之前,**因此不会触发任何订阅函数**。 +需要注意的是,在一个插件中, state 变更或添加(包括调用 `store.$patch()`)都是发生在 store 被激活之前,**因此不会触发任何订阅函数**。 :::warning -如果你使用的是**Vue 2**,Pinia 与 Vue 一样,受制于[相同的响应式警告](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats)。在创建新的 state 属性时,如 `secret` 和 `hasError`,你需要使用 `Vue.set()` (Vue 2.7) 或者 `@vue/composition-api` 的 `set()`(Vue < 2.7)。 +如果你使用的是 **Vue 2**,Pinia 与 Vue 一样,受限于[相同的响应式限制](https://v2.cn.vuejs.org/v2/guide/reactivity.html#检测变化的注意事项)。在创建新的 state 属性时,如 `secret` 和 `hasError`,你需要使用 `Vue.set()` (Vue 2.7) 或者 `@vue/composition-api` 的 `set()` (Vue < 2.7)。 ```js import { set, toRef } from '@vue/composition-api' @@ -148,7 +148,7 @@ pinia.use(({ store }) => { const secretRef = ref('secret') // 如果这些数据是要在 SSR 过程中使用的 // 你应该将其设置在 `$state' 属性上 - // 这样它就会被序列化并在 hydration 过程中被接收 + // 这样它就会被序列化并在激活过程中被接收 set(store.$state, 'secret', secretRef) // 直接在 store 里设置,这样你就可以访问它了。 // 两种方式都可以:`store.$state.secret` / `store.secret`。 @@ -166,7 +166,7 @@ pinia.use(({ store }) => { ```js import { markRaw } from 'vue' -// 根据你的路由器的位置来调整这个 +// 根据你的路由器的位置来调整 import { router } from './router' pinia.use(({ store }) => { @@ -209,7 +209,7 @@ defineStore('search', { }) ``` -然后,该插件可以读取该选项来包装 action ,并替换原始 action: +然后,该插件可以读取该选项来包装 action,并替换原始 action: ```js // 使用任意防抖库 @@ -251,9 +251,9 @@ defineStore( 上述一切功能都有类型支持,所以你永远不需要使用 `any` 或 `@ts-ignore`。 -### 插件类型检查 {#typing-plugins} +### 标注插件类型 {#typing-plugins} -一个 Pinia 插件可按如下方式实现类型检查: +一个 Pinia 插件可按如下方式实现类型标注: ```ts import { PiniaPluginContext } from 'pinia' @@ -282,7 +282,7 @@ declare module 'pinia' { } ``` -然后,它就可以被安全地写入和读取了: +然后,就可以安全地写入和读取它了: ```ts pinia.use(({ store }) => { @@ -295,13 +295,13 @@ pinia.use(({ store }) => { }) ``` -`PiniaCustomProperties` 是一个通用类型,允许你引用 store 的属性。思考一下这个例子,如果把初始选项复制成 `$options`(这只对 option store 有效),如何实现类型检查: +`PiniaCustomProperties` 是一个通用类型,允许你引用 store 的属性。思考一下这个例子,如果把初始选项复制成 `$options`(这只对 option store 有效),如何标注类型: ```ts pinia.use(({ options }) => ({ $options: options })) ``` -我们可以通过使用 `PiniaCustomProperties` 的4种通用类型来实现类型检查: +我们可以通过使用 `PiniaCustomProperties` 的4种通用类型来标注类型: ```ts import 'pinia' @@ -330,7 +330,7 @@ declare module 'pinia' { ### 为新的 state 添加类型 {#typing-new-state} -当添加新的 state 属性(包括 `store` 和 `store.$state` )时,你需要将类型添加到 `PiniaCustomStateProperties` 中。与 `PiniaCustomProperties` 不同的是,它只接收 `State` 泛型: +当添加新的 state 属性(包括 `store` 和 `store.$state` )时,你需要将类型添加到 `PiniaCustomStateProperties` 中。与 `PiniaCustomProperties` 不同的是,它只接收 `State` 泛型: ```ts import 'pinia' @@ -358,12 +358,12 @@ declare module 'pinia' { ``` :::tip -还有一个 `StoreGetters` 类型可以从一个 store 类型中提取 _getters_。你也可以且**只可以**分别通过扩展 `DefineStoreOptions` 和 `DefineSetupStoreOptions` 类型来扩展 _setup stores_ 或 _option stores_ 的选项。 +还有一个可以从一个 store 类型中提取 *getter* 的 `StoreGetters` 类型。你也可以且**只可以**通过扩展 `DefineStoreOptions` 或 `DefineSetupStoreOptions` 类型来扩展 *setup store* 或 *option store* 的选项。 ::: ## Nuxt.js {#nuxt-js} -当[在 Nuxt 中使用 pinia](../ssr/nuxt.md)时,你必须先创建一个 [Nuxt 插件](https://nuxtjs.org/docs/2.x/directory-structure/plugins)。这样你才能访问到 `pinia` 实例: +当[在 Nuxt 中使用 pinia](../ssr/nuxt.md) 时,你必须先创建一个 [Nuxt 插件](https://nuxtjs.org/docs/2.x/directory-structure/plugins)。这样你才能访问到 `pinia` 实例: ```ts // plugins/myPiniaPlugin.js @@ -376,7 +376,7 @@ function MyPiniaPlugin({ store }: PiniaPluginContext) { console.log(`[🍍 ${mutation.storeId}]: ${mutation.type}.`) }) - // 请注意,如果你使用的是TS,则必须添加类型。 + // 请注意,如果你使用的是 TS,则必须添加类型。 return { creationTime: new Date() } } @@ -387,4 +387,4 @@ const myPlugin: Plugin = ({ $pinia }) => { export default myPlugin ``` -注意上面的例子使用的是 TypeScript。如果你使用的是 `.js` 文件,你必须删除类型注释 `PiniaPluginContext` 和 `Plugin` 以及它们的导入语句。 +注意上面的例子使用的是 TypeScript。如果你使用的是 `.js` 文件,你必须删除类型标注 `PiniaPluginContext` 和 `Plugin` 以及它们的导入语句。 diff --git a/packages/docs/zh/core-concepts/state.md b/packages/docs/zh/core-concepts/state.md index 6ad47537..4967b394 100644 --- a/packages/docs/zh/core-concepts/state.md +++ b/packages/docs/zh/core-concepts/state.md @@ -5,7 +5,7 @@ title="Learn all about state in Pinia" /> -在大多数情况下,state 都是你的 store 的核心。人们通常会首先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。 +在大多数情况下,state 都是你的 store 的核心。人们通常会先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得 Pinia 可以同时支持服务端和客户端。 ```js import { defineStore } from 'pinia' @@ -24,7 +24,7 @@ const useStore = defineStore('storeId', { ``` :::tip -如果你使用的是 Vue2,你在 `state` 中创建的数据与 Vue 实例中的 `data` 遵循同样的规则,即 state 对象必须是清晰的,当你想向其**添加新属性**时,你需要调用 `Vue.set()` 。**参考:[Vue#data](https://vuejs.org/v2/api/#data)**。 +如果你使用的是 Vue 2,你在 `state` 中创建的数据与 Vue 实例中的 `data` 遵循同样的规则,即 state 对象必须是清晰的,当你想向其**添加新属性**时,你需要调用 `Vue.set()` 。**参考:[Vue#data](https://v2.cn.vuejs.org/v2/api/#data)**。 ::: ## TypeScript {#typescript} @@ -114,7 +114,7 @@ const useCounterStore = defineStore('counter', { }) ``` -如果你不使用组合式 API,你可以使用 `computed`,`methods`,...,你也可以使用 `mapState()` helper 将 state 属性映射为只读的计算属性: +如果你不能使用组合式 API,但你可以使用 `computed`,`methods`,...,那你可以使用 `mapState()` 辅助函数将 state 属性映射为只读的计算属性: ```js import { mapState } from 'pinia' @@ -130,7 +130,7 @@ export default { myOwnName: 'count', // 你也可以写一个函数来获得对 store 的访问权 double: store => store.count * 2, - // 它可以访问 `this`,但它无法被正确类型检查... + // 它可以访问 `this`,但它没有标注类型... magicValue(store) { return store.someGetter + this.count + this.double }, @@ -141,7 +141,7 @@ export default { #### 可修改的 state {#modifiable-state} -如果你想修改这些 state 属性(例如,如果你有一个表单),你可以使用 `mapWritableState()` 来代替。但注意你不能像 `mapState()` 那样传递一个函数: +如果你想修改这些 state 属性(例如,如果你有一个表单),你可以使用 `mapWritableState()` 作为代替。但注意你不能像 `mapState()` 那样传递一个函数: ```js import { mapWritableState } from 'pinia' @@ -162,14 +162,14 @@ export default { ``` :::tip -对于像数组这样的集合,除非你用 `cartItems = []` 替换整个数组,你不需要 `mapWritableState()`,`mapState()` 就允许你调用集合上的方法。 +对于像数组这样的集合,你并不一定需要使用 `mapWritableState()`,`mapState()` 也允许你调用集合上的方法,除非你想用 `cartItems = []` 替换整个数组。 ::: ## 变更 state {#mutating-the-state} -除了用 `store.count++` 直接改变存储,你还可以调用 `$patch` 方法。它允许你用一个 `state` 的补丁对象在同一时间更改多个属性: +除了用 `store.count++` 直接改变 store,你还可以调用 `$patch` 方法。它允许你用一个 `state` 的补丁对象在同一时间更改多个属性: ```js store.$patch({ @@ -179,7 +179,7 @@ store.$patch({ }) ``` -然而,用这种语法的话,有些变更真的很难实现或者很耗时:任何集合的修改(例如,从数组中推送、移除、拼接一个元素)都需要你创建一个新的集合。因此,`$patch` 方法也接受一个函数来组合这种难以用补丁对象实现的变更。 +不过,用这种语法的话,有些变更真的很难实现或者很耗时:任何集合的修改(例如,从数组中推送、移除、拼接一个元素)都需要你创建一个新的集合。因此,`$patch` 方法也接受一个函数来组合这种难以用补丁对象实现的变更。 ```js cartStore.$patch((state) => { @@ -190,11 +190,11 @@ cartStore.$patch((state) => { -这里的主要区别是,`$patch()` 允许你将多个变更归入 devtools 的一个条目中。同时请注意,**直接修改 `state`,`$patch()` 也会出现在 devtools 中**,而且可以进行 time travel(在 Vue3 中还没有)。 +两种变更 store 方法的主要区别是,`$patch()` 允许你将多个变更归入 devtools 的同一个条目中。同时请注意,**直接修改 `state`,`$patch()` 也会出现在 devtools 中**,而且可以进行 time travel(在 Vue 3 中还没有)。 ## 替换 `state` {#replacing-the-state} -你**不能完全替换掉** store 的 state,因为那会破坏响应性。但是,你可以 _patch_ 它。 +你**不能完全替换掉** store 的 state,因为那样会破坏其响应性。但是,你可以 *patch* 它。 ```js // 这实际上并没有替换`$state` @@ -203,7 +203,7 @@ store.$state = { count: 24 } store.$patch({ count: 24 }) ``` -你也可以通过变更 `pinia` 实例的 `state` 来设置整个应用程序的初始 state。这常用于 [ hydration 的 SSR](../ssr/#state-hydration)。 +你也可以通过变更 `pinia` 实例的 `state` 来设置整个应用的初始 state。这常用于 [SSR 中的激活过程](../ssr/#state-hydration)。 ```js pinia.state.value = {} @@ -211,7 +211,7 @@ pinia.state.value = {} ## 订阅 state {#subscribing-to-the-state} -类似于 Vuex 的 [subscribe 方法](https://vuex.vuejs.org/api/#subscribe),你可以通过 store 的 `$subscribe()` 方法观测 state 及其变化。比起普通的 `watch()`,使用 `$subscribe()` 的好处是 _subscriptions_ 在 _patch_ 后只触发一次(例如,当使用上面的函数版本时)。 +类似于 Vuex 的 [subscribe 方法](https://vuex.vuejs.org/zh/api/index.html#subscribe),你可以通过 store 的 `$subscribe()` 方法侦听 state 及其变化。比起普通的 `watch()`,使用 `$subscribe()` 的好处是 *subscriptions* 在 *patch* 后只触发一次(例如,当使用上面的函数版本时)。 ```js cartStore.$subscribe((mutation, state) => { @@ -227,7 +227,7 @@ cartStore.$subscribe((mutation, state) => { }) ``` -默认情况下,_state subscriptions_ 会被绑定到添加它们的组件上(如果 store 在组件的 `setup()` 里面)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 `{ detached: true }` 作为第二个参数,以将 _state subscription_ 从当前组件中 _detach_: +默认情况下,*state subscription* 会被绑定到添加它们的组件上(如果 store 在组件的 `setup()` 里面)。这意味着,当该组件被卸载时,它们将被自动删除。如果你想在组件卸载后依旧保留它们,请将 `{ detached: true }` 作为第二个参数,以将 *state subscription* 从当前组件中*分离*: ```js export default { @@ -243,7 +243,7 @@ export default { ``` :::tip -你可以在`pinia`实例上侦听整个 state。 +你可以在 `pinia` 实例上侦听整个 state。 ```js watch( diff --git a/packages/docs/zh/getting-started.md b/packages/docs/zh/getting-started.md index 25078cb8..918c8819 100644 --- a/packages/docs/zh/getting-started.md +++ b/packages/docs/zh/getting-started.md @@ -9,12 +9,12 @@ npm install pinia ``` :::tip -如果你的应用使用的是 Vue2,你还需要安装组合式 API 包:`@vue/composition-api`。如果你使用的是 Nuxt,你应该参考[这篇指南](/ssr/nuxt.md)。 +如果你的应用使用的是 Vue 2,你还需要安装组合式 API 包:`@vue/composition-api`。如果你使用的是 Nuxt,你应该参考[这篇指南](/ssr/nuxt.md)。 ::: -如果你正在使用 Vue CLI,你可以试试这个[**非官方插件**](https://github.com/wobsoriano/vue-cli-plugin-pinia)。 +如果你正在使用 Vue CLI,你可以试试这个[**非官方插件**](https://github.com/wobsoriano/vue-cli-plugin-pinia)。 -创建一个 pinia 实例(根 store)并将其传递给应用程序: +创建一个 pinia 实例(根 store)并将其传递给应用: ```js {2,5-6,8} import { createApp } from 'vue' @@ -28,7 +28,7 @@ app.use(pinia) app.mount('#app') ``` -如果你使用的是 Vue2,你还需要安装一个插件,并在应用程序的根部注入创建的 `pinia`: +如果你使用的是 Vue 2,你还需要安装一个插件,并在应用的根部注入创建的 `pinia`: ```js {1,3-4,12} import { createPinia, PiniaVuePlugin } from 'pinia' @@ -41,21 +41,21 @@ new Vue({ // 其他配置... // ... // 请注意,同一个`pinia'实例 - // 可以在同一个页面的多个 Vue 应用程序中使用。 + // 可以在同一个页面的多个 Vue 应用中使用。 pinia, }) ``` -这也将提供 devtools 支持。在 Vue3 中,虽然一些功能仍然不被支持,如 time traveling 和编辑,这是因为 vue-devtools 还没有相关的 API,但是 devtools 有更多针对 Vue3 的功能,而且就开发者的体验来说,Vue3 整体上要好得多。在 Vue2 中,Pinia 使用的是 Vuex 的现有接口(因此不能与 Vuex 一起使用)。 +这样才能提供 devtools 的支持。在 Vue 3 中,一些功能仍然不被支持,如 time traveling 和编辑,这是因为 vue-devtools 还没有相关的 API,但 devtools 也有很多针对 Vue 3 的专属功能,而且就开发者的体验来说,Vue 3 整体上要好得多。在 Vue 2 中,Pinia 使用的是 Vuex 的现有接口(因此不能与 Vuex 一起使用)。 ## Store 是什么?{#what-is-a-store} -Store(如 Pinia)是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,**它承载着全局状态**。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有**三个概念**,[state](./core-concepts/state.md)、[getters](./core-concepts/getters.md) 和 [actions](./core-concepts/actions.md),我们可以假设这些概念相当于组件中的 `data`、 `computed` 和 `methods`。 +Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,**它承载着全局状态**。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有**三个概念**,[state](./core-concepts/state.md)、[getter](./core-concepts/getters.md) 和 [action](./core-concepts/actions.md),我们可以假设这些概念相当于组件中的 `data`、 `computed` 和 `methods`。 ## 应该在什么时候使用 Store? {#when-should-i-use-a-store} -一个 Store 应该包含可以在整个应用程序中访问的数据。这包括在许多地方使用的数据,例如显示在导航栏中的用户信息,以及需要通过页面保存的数据,例如一个非常复杂的多步骤表单。 +一个 Store 应该包含可以在整个应用中访问的数据。这包括在许多地方使用的数据,例如显示在导航栏中的用户信息,以及需要通过页面保存的数据,例如一个非常复杂的多步骤表单。 另一方面,你应该避免在 Store 中引入那些原本可以在组件中保存的本地数据,例如,一个元素在页面中的可见性。 -并非所有的应用程序都需要访问全局状态,但如果你的应用程序确实需要一个全局状态,Pinia 将使你的开发更轻松。 +并非所有的应用都需要访问全局状态,但如果你的应用确实需要一个全局状态,那 Pinia 将使你的开发过程更轻松。 diff --git a/packages/docs/zh/index.md b/packages/docs/zh/index.md index 903ca81e..c7e729ba 100644 --- a/packages/docs/zh/index.md +++ b/packages/docs/zh/index.md @@ -9,11 +9,11 @@ altActionLink: https://stackblitz.com/github/piniajs/example-vue-3-vite features: - title: 💡 所见即所得 - details: 与组件类似的 Store。其 API 的设计旨在让你编写出更易组织的 store 。 + details: 与组件类似的 Store。其 API 的设计旨在让你编写出更易组织的 store。 - title: 🔑 类型安全 details: 类型可自动推断,即使在 JavaScript 中亦可为你提供自动补全功能! - title: ⚙️ 开发工具支持 - details: 不管是 Vue2 还是 Vue3,与 Vue devtools 挂钩的 Pinia 都能给你更好的开发体验。 + details: 不管是 Vue 2 还是 Vue 3,支持 Vue devtools 钩子的 Pinia 都能给你更好的开发体验。 - title: 🔌 可扩展性 details: 可通过事务、同步本地存储等方式扩展 Pinia,以响应 store 的变更。 - title: 🏗 模块化设计 diff --git a/packages/docs/zh/introduction.md b/packages/docs/zh/introduction.md index 4e8b3242..f7dbb4bc 100644 --- a/packages/docs/zh/introduction.md +++ b/packages/docs/zh/introduction.md @@ -5,26 +5,26 @@ title="Get started with Pinia" /> -Pinia [起始](https://github.com/vuejs/pinia/commit/06aeef54e2cad66696063c62829dac74e15fd19e)于 2019 年 11 月左右的一次实验,该实验的目的是设计一个拥有 [组合式 API](https://github.com/vuejs/composition-api) 的 Vue 状态管理库。从那时起,我们就倾向于同时支持 Vue2 和 Vue3,并且不强制要求使用组合式 API,我们的初心至今没有改变。除了**安装**和 **SSR** 等章节之外,其余章节内容的 API 均支持 Vue3 和 Vue2。虽然本文档主要是面向 Vue3 的用户,但在必要时会标注出 Vue2 的内容,因此 Vue2 和 Vue3 的用户都可以阅读本文档。 +Pinia [起始](https://github.com/vuejs/pinia/commit/06aeef54e2cad66696063c62829dac74e15fd19e)于 2019 年 11 月左右的一次实验,其目的是设计一个拥有[组合式 API](https://github.com/vuejs/composition-api) 的 Vue 状态管理库。从那时起,我们就倾向于同时支持 Vue 2 和 Vue 3,并且不强制要求开发者使用组合式 API,我们的初心至今没有改变。除了**安装**和 **SSR** 两章之外,其余章节中提到的 API 均支持 Vue 2 和 Vue 3。虽然本文档主要是面向 Vue 3 的用户,但在必要时会标注出 Vue 2 的内容,因此 Vue 2 和 Vue 3 的用户都可以阅读本文档。 ## 为什么你应该使用 Pinia?{#why-should-i-use-pinia} -Pinia 是 Vue 的专属状态管理库,它允许你跨组件/页面共享状态。如果你熟悉组合式 API 的话,你可能会认为你可以通过一行简单的 `export const state = reactive({})`来共享一个全局状态。对于单页应用程序来说确实是这样的,但如果在服务器端渲染,这可能会使您的应用程序暴露出一些安全漏洞。 如果使用 Pinia,即使在小型单页应用程序中,你也可以获得如下功能: +Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 `export const state = reactive({})` 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。 而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能: - Devtools 支持 - 追踪 actions、mutations 的时间线 - - Store 可呈现于使用到它们的组件中 - - Time travel 让调试更容易 + - 在组件中展示它们所用到的 Store + - 让调试更容易的 Time travel - 热更新 - 不必重载页面即可修改 Store - 开发时可保持当前的 State - 插件:可通过插件扩展 Pinia 功能 -- 为 JS 开发者提供适当的 TypeScript 支持以及 **autocompletion** 功能。 +- 为 JS 开发者提供适当的 TypeScript 支持以及**自动补全**功能。 - 支持服务端渲染 ## 基础示例 {#basic-example} -下面就是以 API 使用 pinia 的基本用法。(为继续阅读本简介请确保你已阅读过了[开始](./getting-started.md)章节)你可以先创建一个 Store: +下面就是 pinia API 的基本用法 (为继续阅读本简介请确保你已阅读过了[开始](./getting-started.md)章节)。你可以先创建一个 Store: ```js // stores/counter.js @@ -54,7 +54,7 @@ export default { const counter = useCounterStore() counter.count++ - // with autocompletion ✨ + // 带有自动补全 ✨ counter.$patch({ count: counter.count + 1 }) // 或者使用 action 代替 counter.increment() @@ -62,7 +62,7 @@ export default { } ``` -为实现更多高级用法,你甚至可以使用一个函数(与组件 `setup()` 类似)来定义一个 Store: +为实现更多高级用法,你甚至可以使用一个函数(与组件 `setup()` 类似)来定义一个 Store: ```js export const useCounterStore = defineStore('counter', () => { @@ -75,7 +75,7 @@ export const useCounterStore = defineStore('counter', () => { }) ``` -如果你还不熟悉 setup() 和组合式 API,别担心,Pinia 也提供了一组类似 Vuex 的 [map helpers](https://vuex.vuejs.org/guide/state.html#the-mapstate-helper)。你可以用和之前一样的方式来定义 Store,然后通过 `mapStores()`、`mapState()` 或 `mapActions()`使用: +如果你还不熟悉 setup() 函数和组合式 API,别担心,Pinia 也提供了一组类似 Vuex 的 [映射 state 的辅助函数](https://vuex.vuejs.org/zh/guide/state.html#mapstate-辅助函数)。你可以用和之前一样的方式来定义 Store,然后通过 `mapStores()`、`mapState()` 或 `mapActions()` 访问: ```js {22,24,28} const useCounterStore = defineStore('counter', { @@ -110,15 +110,15 @@ export default { } ``` -你将会在核心概念部分了解到更多关于每个 _map helper_ 的信息。 +你将会在核心概念部分了解到更多关于每个**映射辅助函数**的信息。 -## 为什么命名为 _Pinia_?{#why-pinia} +## 为什么取名 *Pinia*?{#why-pinia} -Pinia (发音为 `/piːnjʌ/`,类似英文中的 “peenya”) 是最接近有效包名 piña(西班牙语中的 _pineapple_,即“菠萝”)的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。 它(菠萝)也是一种原产于南美洲的美味热带水果。 +Pinia (发音为 `/piːnjʌ/`,类似英文中的 “peenya”) 是最接近有效包名 piña (西班牙语中的 *pineapple*,即“菠萝”) 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。 它(菠萝)也是一种原产于南美洲的美味热带水果。 ## 更真实的示例 {#a-more-realistic-example} -这是一个更完整的 Pinia API 示例,在 JavaScript 中也使用了类型提示。对于某些人来说,可能足以在不进一步阅读的情况下直接开始阅读本节内容,但我们仍然建议你继续阅读文档的其余部分,甚至跳过此示例,在阅读完所有**核心概念**之后再回来。 +这是一个更完整的 Pinia API 示例,在 JavaScript 中也使用了类型提示。对于某些开发者来说,可能足以在不进一步阅读的情况下直接开始阅读本节内容,但我们仍然建议你先继续阅读文档的其余部分,甚至跳过此示例,在阅读完所有**核心概念**之后再回来。 ```js import { defineStore } from 'pinia' @@ -134,7 +134,7 @@ export const useTodos = defineStore('todos', { }), getters: { finishedTodos(state) { - // autocompletion! ✨ + // 自动补全! ✨ return state.todos.filter((todo) => todo.isFinished) }, unfinishedTodos(state) { @@ -145,7 +145,7 @@ export const useTodos = defineStore('todos', { */ filteredTodos(state) { if (this.filter === 'finished') { - // 调用其他带有 autocompletion 的 getters ✨ + // 调用其他带有自动补全的 getters ✨ return this.finishedTodos } else if (this.filter === 'unfinished') { return this.unfinishedTodos @@ -156,7 +156,7 @@ export const useTodos = defineStore('todos', { actions: { // 接受任何数量的参数,返回一个 Promise 或不返回 addTodo(text) { - // 你可以直接 mutate 该状态 + // 你可以直接变更该状态 this.todos.push({ text, id: this.nextId++, isFinished: false }) }, }, @@ -165,28 +165,28 @@ export const useTodos = defineStore('todos', { ## 对比 Vuex {#comparison-with-vuex} -Pinia 起源于一次探索 Vuex 下一个迭代的实验,所以其结合了 Vuex 5 核心团队讨论中的许多想法。最终,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分功能,所以决定将其作为新的推荐方案来代替 Vuex。 +Pinia 起源于一次探索 Vuex 下一个迭代的实验,因此结合了 Vuex 5 核心团队讨论中的许多想法。最后,我们意识到 Pinia 已经实现了我们在 Vuex 5 中想要的大部分功能,所以决定将其作为新的推荐方案来代替 Vuex。 与 Vuex 相比,Pinia 不仅提供了一个更简单的 API,也提供了符合组合式 API 风格的 API,最重要的是,搭配 TypeScript 一起使用时有非常可靠的类型推断支持。 -### RFCs {#rfcs} +### RFC {#rfcs} -最初,Pinia 没有经过任何 RFC 的流程。我基于自己开发应用程序的经验,同时通过阅读其他人的代码,为使用 Pinia 的用户工作,以及在 Discord 上回答问题等方式验证了一些想法。 -这些使我产出了这样一个可行的解决方案,并适应各种场景和应用规模。我一直在保持其核心 API 不变的情况下发布新版本,同时不断优化本库。 +最初,Pinia 没有经过任何 RFC 的流程。我基于自己开发应用的经验,同时通过阅读其他人的代码,为使用 Pinia 的用户工作,以及在 Discord 上回答问题等方式验证了一些想法。 +这些经历使我产出了这样一个可用的解决方案,并适应了各种场景和应用规模。我会一直在保持其核心 API 不变的情况下发布新版本,同时不断优化本库。 -现在 Pinia 已经成为默认的状态管理解决方案,它和 Vue 生态系统中的其他核心库一样,都要经过 RFC 流程,其 API 进入稳定状态。 +现在 Pinia 已经成为推荐的状态管理解决方案,它和 Vue 生态系统中的其他核心库一样,都要经过 RFC 流程,它的 API 也已经进入稳定状态。 ### 对比 Vuex 3.x/4.x {#comparison-with-vuex-3-x-4-x} -> Vuex 3.x 只适配 Vue2,而 Vuex 4.x 是适配 Vue3 的。 +> Vuex 3.x 只适配 Vue 2,而 Vuex 4.x 是适配 Vue 3 的。 -Pinia API 与 Vuex ≤4 有很大不同,即: +Pinia API 与 Vuex(<=4) 也有很多不同,即: -- _mutations_ 已弃用。它们经常被认为是**极其冗长的**。它们初衷是带来 devtools 的集成方案,但这已不再是一个问题了。 -- 无需要创建自定义的复杂包装器来支持 TypeScript,一切都被类型化了,API 的设计方式是尽可能地利用 TS 类型推理。 -- 无过多的魔法字符串注入,只需要导入函数并调用它们,然后享受 autocompletion 的乐趣就好。 -- 无需要动态添加 Store,它们默认都是动态的,甚至你都不会注意到这点。注意,你仍然可以在任何时候手动使用一个 Store 来注册它,但因为它是自动的,所以你不需要担心它。 +- *mutation* 已被弃用。它们经常被认为是**极其冗余的**。它们初衷是带来 devtools 的集成方案,但这已不再是一个问题了。 +- 无需要创建自定义的复杂包装器来支持 TypeScript,一切都可标注类型,API 的设计方式是尽可能地利用 TS 类型推理。 +- 无过多的魔法字符串注入,只需要导入函数并调用它们,然后享受自动补全的乐趣就好。 +- 无需要动态添加 Store,它们默认都是动态的,甚至你可能都不会注意到这点。注意,你仍然可以在任何时候手动使用一个 Store 来注册它,但因为它是自动的,所以你不需要担心它。 - 不再有嵌套结构的**模块**。你仍然可以通过导入和使用另一个 Store 来隐含地嵌套 stores 空间,虽然是 Pinia 从设计上提供的是一个扁平的结构,但仍然能够在 Store 之间进行交叉组合。**你甚至可以让 Stores 有循环依赖关系**。 -- 没有**命名的模块**。考虑到 Store 的扁平架构,Store 的命名取决于它们的定义方式,你甚至可以说所有 Store 都应该命名。 +- 不再有**可命名的模块**。考虑到 Store 的扁平架构,Store 的命名取决于它们的定义方式,你甚至可以说所有 Store 都应该命名。 -关于如何将现有 Vuex ≤4 项目转化为使用 Pinia 的更多详细说明,请参阅[ Vuex 迁移指南](./cookbook/migration-vuex.md)。 +关于如何将现有 Vuex(<=4) 的项目转化为使用 Pinia 的更多详细说明,请参阅 [Vuex 迁移指南](./cookbook/migration-vuex.md)。 diff --git a/packages/docs/zh/ssr/index.md b/packages/docs/zh/ssr/index.md index 3bdc1ea4..1400801e 100644 --- a/packages/docs/zh/ssr/index.md +++ b/packages/docs/zh/ssr/index.md @@ -30,7 +30,7 @@ app.use(pinia) router.beforeEach((to) => { // ✅这会正常工作,因为它确保了正确的 store 被用于 - // 当前正在运行的应用程序 + // 当前正在运行的应用 const main = useMainStore(pinia) if (to.meta.requiresAuth && !main.isLoggedIn) return '/login' @@ -47,9 +47,9 @@ export default { } ``` -## State hydration {#state-hydration} +## State 激活 {#state-hydration} -为了 hydrate 初始 state,你需要确保 rootState 包含在 HTML 中的某个地方,以便 Pinia 稍后能够接收到它。根据你服务端所渲染的内容,**为了安全你应该转义 state**。我们推荐 Nuxt.js 目前使用的 [@nuxt/devalue](https://github.com/nuxt-contrib/devalue): +为了激活初始 state,你需要确保 rootState 包含在 HTML 中的某个地方,以便 Pinia 稍后能够接收到它。根据你服务端所渲染的内容,**为了安全你应该转义 state**。我们推荐 Nuxt.js 目前使用的 [@nuxt/devalue](https://github.com/nuxt-contrib/devalue): ```js import devalue from '@nuxt/devalue' @@ -63,7 +63,7 @@ app.use(pinia) // 渲染页面后,rootState 被建立, // 可以直接在 `pinia.state.value`上读取。 -// 序列化,转义(如果 state 的内容可以被用户改变,这点就非常重要,几乎都是这样的) +// 序列化,转义(如果 state 的内容可以被用户改变,这点就非常重要,几乎都是这样的) // 并将其放置在页面的某处 // 例如,作为一个全局变量。 devalue(pinia.state.value) @@ -95,9 +95,9 @@ export default viteSSR( ) ``` -你可以根据你的需要使用 `@nuxt/devalue` 的[其他替代品](https://github.com/nuxt-contrib/devalue#see-also),例如,如果你也能用 `JSON.stringify()`/`JSON.parse()` 来序列化和解析你的 state,**这样你可以把性能提高很多。** +你可以根据你的需要使用 `@nuxt/devalue` 的[其他替代品](https://github.com/nuxt-contrib/devalue#see-also),例如,你也可以用 `JSON.stringify()`/`JSON.parse()` 来序列化和解析你的 state,**这样你可以把性能提高很多。** -也可以根据你的环境调整这个策略。但确保在客户端调用任何 `useStore()` 函数之前,对 pinia 的 state 进行 hydrate。例如,如果我们将 state 序列化为一个 `