diff --git a/docs/zh-cn/structure.md b/docs/zh-cn/structure.md index 5fc5778ef..ce60d1470 100644 --- a/docs/zh-cn/structure.md +++ b/docs/zh-cn/structure.md @@ -6,8 +6,9 @@ Vuex 并不限制你的代码结构,但是制定了一套需要遵守的规则 2. 只有 mutation handlers 可以改变 state; 3. Mutations 必须是同步的,它们做的应该仅仅是改变 state; 4. 所有类似数据获取的异步操作细节都应封装在 actions 里面。 +5. 组件通过 getters 从 store 中获取 state,并通过调用 actions 来改变 state。 -Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数**。只需要遵循以上的准则,怎么组织代码就取决于你自己了。最简单的 Vuex store 实例甚至可以在 [单个文件](https://github.com/vuejs/vuex/blob/master/examples/counter/vuex.js) 中声明!然而这在真正的项目里显然是行不通的,所以这里有些根据不同应用规模推荐的不同结构。 +Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数**。只需要遵循以上的准则,怎么组织代码就取决于你自己了。不过,遵循一些规则能够让你更快地熟悉其他使用 vuex 的项目。这里介绍了一些适应不同项目规模的应用结构。 ### 简单的项目 @@ -26,7 +27,9 @@ Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数** └── mutations.js # exports all mutations ``` -参见 [TodoMVC 示例](https://github.com/vuejs/vuex/tree/master/examples/todomvc). +参见[计数器 示例](https://github.com/vuejs/vuex/tree/master/examples/todomvc) 或 [TodoMVC 示例](https://github.com/vuejs/vuex/tree/master/examples/todomvc). + +另外,你也可以将 mutations 拆分到不同的文件中去。 ### 中型到大型项目 @@ -42,13 +45,13 @@ Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数** ├── components │   ├── App.vue │   └── ... -└── store - ├── actions.js # exports all actions - ├── index.js - ├── modules - │   ├── cart.js # state and mutations for cart - │   └── products.js # state and mutations for products - └── mutation-types.js # constants +└── vuex + ├── actions.js # exports all actions + ├── store.js # where we assemble modules and export the store + ├── mutation-types.js # constants + └── modules +    ├── cart.js # state and mutations for cart +    └── products.js # state and mutations for products ``` 一个典型的模块: @@ -58,46 +61,68 @@ Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数** import { RECEIVE_PRODUCTS, ADD_TO_CART } from '../mutation-types' // 该模块的初始状态 -export const productsInitialState = [] +const state = { + all: [] +} // 相关的 mutations -export const productsMutations = { +const mutations = { [RECEIVE_PRODUCTS] (state, products) { - state.products = products + state.all = products }, - [ADD_TO_CART] ({ products }, productId) { - const product = products.find(p => p.id === productId) - if (product.inventory > 0) { - product.inventory-- - } + [ADD_TO_CART] (state, productId) { + state.all.find(p => p.id === productId).inventory-- } } + +export default { + state, + mutations +} ``` -在 `store/index.js` 里我们把多个模块集合在一起来创建 Vuex 实例: +在 `vuex/store.js` 里我们把多个模块集合在一起来创建 Vuex 实例: ``` js import Vue from 'vue' import Vuex from '../../../src' import * as actions from './actions' // 导入各个模块的初始状态和 mutations -import { cartInitialState, cartMutations } from './modules/cart' -import { productsInitialState, productsMutations } from './modules/products' +import cart from './modules/cart' +import products from './modules/products' Vue.use(Vuex) export default new Vuex.Store({ - // ... - // 将各个模块的状态组合成最终的根状态 (root state) - state: { - cart: cartInitialState, - products: productsInitialState - }, - // mutations 选项可以是一个包含多个对象的数组 - mutations: [cartMutations, productsMutations] + // 组合各个模块 + modules: { + cart, + products + } }) ``` +在这里,`cart` 模块的初始状态会作为 `store.state.cart` 被设置到底层 state 树上。另外,**所有在子模块上定义的 mutations 都只能改变当前相关联子模块上的 state 子树**。所以在 `cart` 模块上定义的 mutations 接收到的第一个参数将会是 `store.state.cart`。 + +state 子树的根节点不能在模块内部改写。比如这样的写法是无效的: + +``` js +const mutations = { + SOME_MUTATION (state) { + state = { ... } + } +} +``` + +可替代的写法是将真实的 state 作为子树本身的属性在存储: + +``` js +const mutations = { + SOME_MUTATION (state) { + state.value = { ... } + } +} +``` 由于一个模块导出的仅仅是对象和函数,它们也是非常易于测试和维护的。当然,你也可以按你的喜好和需求对这样的组织方式进行修改。