Forráskód Böngészése

update docs (finish chinese edits)

Evan You 9 éve
szülő
commit
db2815909f

+ 1 - 0
docs/LANGS.md

@@ -1 +1,2 @@
 * [English](en/)
+* [简体中文](zh-cn/)

+ 1 - 1
docs/en/api.md

@@ -5,7 +5,7 @@
 ``` js
 import Vuex from 'vuex'
 
-const vuex = new Vuex.Store({ ...options })
+const store = new Vuex.Store({ ...options })
 ```
 
 ### Vuex.Store Constructor Options

+ 1 - 1
docs/en/concepts.md

@@ -1,6 +1,6 @@
 # Core Concepts
 
-You can use the `Vuex.Store` constructor to create Vuex stores. Each Vuex store consists of three types of "ingredients":
+You can use the `Vuex.Store` constructor to create Vuex stores. In most cases, you only need a single store each application. Each Vuex store consists of three types of "ingredients":
 
 - **State**: A plain object representing the application state.
 

+ 1 - 1
docs/en/middlewares.md

@@ -23,7 +23,7 @@ const store = new Vuex.Store({
 })
 ```
 
-By default, a middleware receives the actual `state` object. Since middlewares are primarily used for debugging purposes, they are **not allowed to mutate the state**.
+By default, a middleware receives the actual `state` object. Since middlewares are primarily used for debugging purposes or data persistence, they are **not allowed to mutate the state**.
 
 Sometimes a middleware may want to receive "snapshots" of the state, and also compare the post-mutation state with pre-mutation state. Such middlewares must declare the `snapshot: true` option:
 

+ 11 - 2
docs/en/mutations.md

@@ -49,7 +49,16 @@ Here `10` will be passed to the mutation handler as the second argument followin
 Since a Vuex store's state is made reactive by Vue, when we mutate the state, Vue components observing the state will update automatically. This also means Vuex mutations are subject to the same reactivity caveats when working with plain Vue:
 
 1. Prefer initializing your store's initial state with all desired fields upfront.
-2. When adding new properties to an Object, you should either use `Vue.set(obj, 'newProp', 123)`, or replace that Object with a fresh one, e.g. `state.obj = { ...state.obj, newProp: 123 }` (Using stage-2 [object spread syntax](https://github.com/sebmarkbage/ecmascript-rest-spread) here).
+
+2. When adding new properties to an Object, you should either:
+
+  - Use `Vue.set(obj, 'newProp', 123)`, or -
+
+  - Replace that Object with a fresh one. For example, using the stage-2 [object spread syntax](https://github.com/sebmarkbage/ecmascript-rest-spread) we can write it like this:
+
+  ``` js
+  state.obj = { ...state.obj, newProp: 123 }
+  ```
 
 ### Using Constants for Mutation Names
 
@@ -82,6 +91,6 @@ Whether to use constants is largely a preference - it can be helpful in large pr
 
 ### On to Actions
 
-Manually calling `store.dispatch` is possible, but in practice, we will rarely do this in our component code. Most of the time we will be calling [actions](actions.md), which can encapsulate more complex logic such as async data fetching.
+So far, we've triggering mutations by manually calling `store.dispatch`. This is a viable approach, but in practice, we will rarely do this in our component code. Most of the time we will be calling [actions](actions.md), which can encapsulate more complex logic such as async data fetching.
 
 Also, one important rule to remember: all mutation handlers must be **synchronous**. Any async operations belong in actions.

+ 1 - 1
docs/zh-cn/SUMMARY.md

@@ -11,7 +11,7 @@
 - [应用结构](structure.md)
 - [中间件](middlewares.md)
 - [严格模式](strict.md)
-- [表单控制](forms.md)
+- [表单处理](forms.md)
 - [测试](testing.md)
 - [热重载](hot-reload.md)
 - [API Reference](api.md)

+ 31 - 37
docs/zh-cn/actions.md

@@ -2,18 +2,18 @@
 
 Actions 是用于 dispatch mutations 的函数。Actions 可以是异步的,一个 action 可以 dispatch 多个 mutations.
 
-一个 action 描述了有什么事情应该发生,把本应该在组件中调用的逻辑细节抽象出来。当一个组件需要做某件事时,只需要调用一个 action —— 并不需要关心 到底是 callback 还是一个返回值,因为 actions 会把结果直接反应给 state,state 改变时会触发组件的 DOM 更新 —— 组件完全和 action 要做的事情解耦
+一个 action 描述了有什么事情应该发生,把本应该在组件中调用的逻辑细节抽象出来。当一个组件需要做某件事时,只需要调用一个 action —— 组件本身并不需要关心具体的后果:不需要提供回调函数也不需要期待返回值,因为 actions 的结果一定是 state 产生了变化,而 state 一旦变化,便会触发组件的 DOM 更新。 这样,组件便完全和 action 的具体逻辑解耦了
 
-因为,我们通常在 actions 中做 API 相关的请求,并把『组件调用 actions、mutations 被 actions 触发』过程中的异步请求隐藏在其中
+因此,我们通常在 actions 中做 API 相关的请求。通过 actions 的封装,我们使得组件和 mutations 都不需要关心这些异步逻辑
 
-> Vuex actions 和 flux 中的 "actions creators" 是一样的,但是我觉得 flux 这样的定义会让人更疑惑
+> Vuex actions 和 Flux 中的 "action creators" 是等同的概念,但是我觉得这个定义常让人感到困惑(比如分不清 actions 和 action creators)
 
 ### 简单的 Actions
 
-通常一个 action 触发一个 mutation. Vuex 提供一个捷径去定义这样的 actions:
+最简单的情况下,一个 action 即触发一个 mutation。Vuex 提供一个快捷的方式去定义这样的 actions:
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state: {
     count: 1
   },
@@ -23,7 +23,7 @@ const vuex = new Vuex({
     }
   },
   actions: {
-    // shorthand
+    // 快捷定义
     // 只要提供 mutation 名
     increment: 'INCREMENT'
   }
@@ -33,23 +33,23 @@ const vuex = new Vuex({
 调用 action:
 
 ``` js
-vuex.actions.increment(1)
+store.actions.increment(1)
 ```
 
 这相当于调用:
 
 ``` js
-vuex.dispatch('INCREMENT', 1)
+store.dispatch('INCREMENT', 1)
 ```
 
 注意所以传递给 action 的参数同样会传递给 mutation handler.
 
-### Thunk Actions
+### 正常 Actions
 
-当 actions 里存在逻辑或者异步操作时怎么办?我们可以定义 **Thunks(返回另一个函数的函数) actions**:
+对于包含逻辑或是异步操作的 actions,则用函数来定义。Actions 函数获得的第一个参数永远是其所属的 store 实例:
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state: {
     count: 1
   },
@@ -59,23 +59,21 @@ const vuex = new Vuex({
     }
   },
   actions: {
-    incrementIfOdd: function (x) {
-      return function (dispatch, state) {
-        if ((state.count + 1) % 2 === 0) {
-          dispatch('INCREMENT', x)
-        }
+    incrementIfOdd: (store, x) => {
+      if ((store.state.count + 1) % 2 === 0) {
+        store.dispatch('INCREMENT', x)
       }
     }
   }
 })
 ```
 
-在这里,外部的函数接受传递进来的参数,之后返回一个带两个参数的函数:第一个参数是 `dispatch` 函数,另一个是 `state`. 我们在这里用 ES2015 语法中的箭头函数简化代码,使其更清晰好看
+通常我们会用 ES6 的参数解构 (arguments destructuring) 语法来使得函数体更简洁
 
 ``` js
 // ...
 actions: {
-  incrementIfOdd: x => (dispatch, state) => {
+  incrementIfOdd: ({ dispatch, state }, x) => {
     if ((state.count + 1) % 2 === 0) {
       dispatch('INCREMENT', x)
     }
@@ -83,30 +81,28 @@ actions: {
 }
 ```
 
-下面是更简单的语法糖:
+同时,简单 actions 的快捷定义其实只是如下函数的语法糖:
 
 ``` js
 actions: {
   increment: 'INCREMENT'
 }
-// ... 相当于:
+// ... 上面的定义等同于:
 actions: {
-  increment: (...args) => dispatch => dispatch('INCREMENT', ...args)
+  increment: ({ dispatch }, ...payload) => {
+    dispatch('INCREMENT', ...payload)
+  }
 }
 ```
 
-Why don't we just define the actions as simple functions that directly access `vuex.state` and `vuex.dispatch`? The reason is that such usage couples the action functions to the specific vuex instance. By using the thunk syntax, our actions only depend on function arguments and nothing else - this important characteristic makes them easy to test and hot-reloadable!
-
-???
-
 ### 异步 Actions
 
-我们能像 thunk 一样定义异步 actions
+异步 actions 同样使用函数定义:
 
 ``` js
 // ...
 actions: {
-  incrementAsync: x => dispatch => {
+  incrementAsync: ({ dispatch }, x) => {
     setTimeout(() => {
       dispatch('INCREMENT', x)
     }, 1000)
@@ -114,27 +110,25 @@ actions: {
 }
 ```
 
-当在检查购物车时,更好的做法是触发多个不同的 mutations:一个在开始检查购物车时触发,一个在成功后触发,还有一个在失败时触发。
+举个更实在的例子,比如一个购物车。当用户结账时,我们可能需要在 checkout 这一个 action 中触发多个不同的 mutations:一个在开始检查购物车时触发,一个在成功后触发,还有一个在失败时触发。
 
 ``` js
 // ...
 actions: {
-  checkout: products => (dispatch, state) => {
-    // save the current in cart items
+  checkout: ({ dispatch, state }, products) => {
+    // 保存结账前的购物车内容
     const savedCartItems = [...state.cart.added]
-    // send out checkout request, and optimistically
-    // clear the cart
+    // 发出结账的请求,并且清空购物车
     dispatch(types.CHECKOUT_REQUEST)
-    // the shop API accepts a success callback and a failure callback
-    shop.buyProducts(
+    // 假设我们的后台 API 接受一个成功回调和一个错误回调
       products,
-      // handle success
+      // 结账成功
       () => dispatch(types.CHECKOUT_SUCCESS),
-      // handle failure
+      // 结账失败,将购物车恢复到结账之前的状态
       () => dispatch(types.CHECKOUT_FAILURE, savedCartItems)
     )
   }
 }
 ```
 
-这样一来,所以需要检查购物车的组件只需要调用 `vuex.actions.checkout(products)`.
+这里有相对复杂的异步逻辑,但是购物车的组件依然只需要简单地调用 `store.actions.checkout(products)` 即可.

+ 11 - 13
docs/zh-cn/api.md

@@ -1,14 +1,14 @@
 # API
 
-### 构造器
+### Vuex.Store
 
 ``` js
 import Vuex from 'vuex'
 
-const vuex = new Vuex({ ...options })
+const store = new Vuex.Store({ ...options })
 ```
 
-### 构造器 options
+### Vuex.Store 构造选项
 
 - **state**
 
@@ -32,12 +32,12 @@ const vuex = new Vuex({ ...options })
 
   - type: `Object | Array<Object>`
 
-    入口 key 为 action 名的对象,value 可能为
+    一个以 action 名为 key 的对象,value 可能为
 
     1. 一个 mutation 名字的 string, 或
-    2. 一个 thunk action 创建函数(thunk action creator function)
+    2. 一个函数。该函数将获取 store 实例为第一个参数,以及其他可能的 payload 参数。
 
-    Vuex 会处理这些入口,并创建可以被调用的 action 函数,暴露到实例中的 `actions` 属性
+    Vuex 会将他们转化为可以被调用的 action 函数,并暴露到 store 实例的 `actions` 对象上
 
     如果传来一个对象数组,这些对象会自动合并到一个对象中。
 
@@ -64,11 +64,11 @@ const vuex = new Vuex({ ...options })
   - type: `Boolean`
   - default: `false`
 
-    使 Vuex 实例进入严格模式。严格模式中,在 mutation handler 外部对 Vuex state 做任何操作均会抛出错误。
+    使 Vuex store 实例进入严格模式。严格模式中,在 mutation handler 外部对该 store 的 state 做任何操作均会抛出错误。
 
     [详细](strict.md)
 
-### 实例属性
+### Vuex.Store 实例属性
 
 - **state**
 
@@ -82,14 +82,12 @@ const vuex = new Vuex({ ...options })
 
     可被调用的 action 函数。
 
-### 实例方法
+### Vuex.Store 实例方法
 
 - **dispatch(mutationName: String, ...args)**
 
-  Directly dispatch a mutation. This is useful in certain situations are in general you should prefer using actions in application code.
-
-  ???
+  直接触发一个 mutation。在一些特殊情况下会需要用到这个方法,但通常来说,在组件中应当尽量通过调用 actions 来触发 mutation。
 
 - **hotUpdate(newOptions: Object)**
 
-  热更新新的 actions 和 mutations. [详细](hot-reload.md)
+  热更新 actions 和 mutations. [详细](hot-reload.md)

+ 9 - 9
docs/zh-cn/concepts.md

@@ -1,33 +1,33 @@
 # 核心概念
 
-和 Vue 一样,Vuex 暴露一个 `Vuex` 构造函数,你可以实例化一个 `Vuex 实例`。一般情况下,一个应用中只需要一个 Vuex 实例。你可以把它当成一个『强化版的 store』
+你可以使用 `Vuex.Store` 构造函数来创建 Vuex store 实例。一般情况下,一个应用中只需要一个 store 实例
 
-每个 Vuex 实例由三个部分组成:
+每个 Vuex store 实例由三个部分组成:
 
 - **State**: 一个反映应用状态的纯对象。
 
-- **Mutations**: 一些用于改变状态的函数。Mutations **一定是同步的**。
+- **Mutations**: 一些用于改变状态的函数。Mutations **必须是同步的**。
 
 - **Actions**: 一些用于触发 (dispatch) mutations 的函数。一个 action 可以包含异步操作,并且可以触发多个 mutations.
 
-我们把 *mutations* 和 *actions* 分开而不是直接用函数去操作 state,原因是我们希望把 mutation 和异步操作分离。许多应用之所以复杂,正是源自于这两者的耦合。我们解耦两者后,它们都会变得更清晰和易于测试。
+我们把 *mutations* 和 *actions* 分开而不是直接用函数去操作 state,原因是我们希望把*对状态的修改*和*异步操作*分离。许多应用之所以复杂,正是源自于这两者的耦合。我们解耦两者后,它们都会变得更清晰和易于测试。
 
 > 如果你熟悉 Flux,在这里要注意两者的一些差异:Vuex mutations 相当于 Flux 的 **actions**, 而 Vuex 的 actions 相当于 Flux 的 **action creators**.
 
-### 创建一个 Vuex 实例
+### 创建一个 Vuex Store 实例
 
-> **NOTE:** 我们将用 ES2015 语法写接下来的示例代码。如果你还没开始接触 ES2015,那么你应该[现在就开始](https://babeljs.io/docs/learn-es2015/)! 我们还默认你已经熟悉 [Building Large-Scale Apps with Vue.js](http://vuejs.org/guide/application.html) 中所提到的概念。
+> **NOTE:** 我们将用 ES2015 语法写接下来的示例代码。如果你还没开始接触 ES2015,那么你应该[现在就开始学习](https://babeljs.io/docs/learn-es2015/)! 我们还默认你已经熟悉 [Building Large-Scale Apps with Vue.js](http://vuejs.org/guide/application.html) 中所提到的概念。
 
-创建一个 Vuex 实例非常简单——只需要把以上提到的三个部分放到一起:
+创建一个 Vuex store 实例非常简单——只需要把以上提到的三个部分放到一起:
 
 ``` js
 import Vuex from 'vuex'
 
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state: { ... },
   actions: { ... },
   mutations: { ... }
 })
 ```
 
-实例化后,你就能通过 `vuex.state` 访问 state, 通过 `vuex.actions` 访问 actions 函数。你不能直接访问 mutation 函数 —— 你只能通过调用 actions 或是 `vuex.disptach()` 来触发 mutations。接下来我们会更详细地讨论这几个概念。
+实例化后,你就能通过 `store.state` 访问 state, 通过 `store.actions` 访问 actions 函数。你不能直接访问 mutation 函数 —— 你只能通过调用 actions 或是 `store.disptach()` 来触发 mutations。接下来我们会更详细地讨论这几个概念。

+ 11 - 13
docs/zh-cn/data-flow.md

@@ -1,11 +1,11 @@
 # 数据流
 
-为了更好地理解 Vuex app 中的数据流,我们来做一个简单的计数器 app。这个例子仅仅用于解释一些概念,实际上你并不需要在这种简单的场合使用 Vuex.
+为了更好地理解 Vuex app 中的数据流,我们来开发一个简单的计数器 app。注意:这个例子仅仅是为了更好地解释概念,在实际情况中并不需要在这种简单的场合使用 Vuex.
 
-### Setup
+### 引入并加载 Vuex
 
 ``` js
-// vuex.js
+// store.js
 import Vue from 'vue'
 import Vuex from 'vuex'
 
@@ -42,10 +42,10 @@ const actions = {
 }
 ```
 
-### 创建 Vuex 实例
+### 创建 Store 实例
 
 ``` js
-export default new Vuex({
+export default new Vuex.Store({
   state,
   mutations,
   actions
@@ -67,27 +67,25 @@ export default new Vuex({
 **Script**
 
 ``` js
-import vuex from './vuex.js'
+import store from './store.js'
 
 export default {
   computed: {
     // 在 computed 属性内绑定 state
     count () {
-      return vuex.state.count
+      return store.state.count
     }
   },
   methods: {
-    increment: vuex.actions.increment,
-    decrement: vuex.actions.decrement
+    increment: store.actions.increment,
+    decrement: store.actions.decrement
   }
 }
 ```
 
-你会注意到组件本身非常简洁:它仅仅显示了 Vuex 实例中的一些 state、在用户输入时调用了一些 vuex actions.
+你会注意到组件本身非常简单:它所做的仅仅是绑定到 state、然后在用户输入时调用 actions.
 
-You will also notice the data flow is unidirectional, as it should be in Flux:
-
-???
+你也会发现整个应用的数据流是单向的,正如 Flux 最初所定义的那样:
 
 <p align="center">
   <img width="700px" src="vuex.png">

+ 6 - 6
docs/zh-cn/forms.md

@@ -1,14 +1,14 @@
-# 表单控制
+# 表单处理
 
-当在严格模式中使用 Vuex 时,属于 Vuex 的 state 在使用 `v-model` 时会比较棘手:
+当在严格模式中使用 Vuex 时,在属于 Vuex 的 state 上使用 `v-model` 会比较棘手:
 
 ``` html
 <input v-model="obj.message">
 ```
 
-这里的 `obj` 是在 computed 属性中返回的 Vue state 中的一个对象,在用户输入时,`v-model` 会直接改变 `obj.message`。在严格模式中,因为你只能通过 Vuex mutation handler 改变 state, 所以这里会抛出一个错误。
+假设这里的 `obj` 是在计算属性中返回的一个属于 Vuex store 的对象,在用户输入时,`v-model` 会试图直接修改 `obj.message`。在严格模式中,由于这个修改不是在 mutation handler 中执行的, 这里会抛出一个错误。
 
-用 『Vuex 方式』 去解决这个问题的方法是:在 input 中绑定 value,在 `input` 或者 `change` 事件中调用 action:
+用『Vuex 的思维』去解决这个问题的方法是:给 `<input>` 中绑定 value,然后侦听 `input` 或者 `change` 事件,在事件回调中调用 action:
 
 ``` html
 <input :value="obj.message" @input="updateMessage">
@@ -22,7 +22,7 @@ methods: {
 }
 ```
 
-`updateMessage` action 会 dispatch `'UPDATE_MESSAGE'`, 下面是 mutation handler:
+我们假设 `updateMessage` action 会 dispatch `'UPDATE_MESSAGE'`, 下面是 mutation handler:
 
 ``` js
 // ...
@@ -33,4 +33,4 @@ mutations: {
 }
 ```
 
-必须承认,这样做比简单地使用 `v-model` 要啰嗦得多,但这换来的是 state 的改变更加清晰和可被跟踪。实际上,Vuex 并不是想你把所有的 state 都放到 Vuex 实例中去 —— 如果有些 state 你不希望去跟踪,你就应该放在 Vuex 外面(比如组件里面),这样就可以愉快地使用 `v-model` 了。
+必须承认,这样做比简单地使用 `v-model` 要啰嗦得多,但这换来的是 state 的改变更加清晰和可被跟踪。另一方面,Vuex 并强制要求所有的状态都必须放在 Vuex store 中 —— 如果有些状态你觉得并没有需要对其变化进行追踪,那么你完全可以把它放在 Vuex 外面(比如作为组件的本地状态),这样就可以愉快地使用 `v-model` 了。

+ 8 - 8
docs/zh-cn/hot-reload.md

@@ -1,26 +1,26 @@
 # 热重载
 
-Vuex 支持在开发中热重载 actions 和 mutations(使用 Webpack 的 [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html))。你也可以在 Browserify 里使用 [browserify-hmr](https://github.com/AgentME/browserify-hmr/) plugin.
+Vuex 支持在开发中热重载 actions 和 mutations(使用 Webpack 的 [Hot Module Replacement API](https://webpack.github.io/docs/hot-module-replacement.html))。你也可以在 Browserify 里使用 [browserify-hmr](https://github.com/AgentME/browserify-hmr/) 插件来实现同样的功能。
 
-只需要简单地调用 `vuex.hotUpdate()`:
+只需要简单地调用 `store.hotUpdate()`:
 
 ``` js
 // ...
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state,
   actions,
   mutations
 })
 
 if (module.hot) {
-  // 使 actions 和 mutations 成为热重载模块
+  // 使 actions 和 mutations 成为热重载模块
   module.hot.accept(['./actions', './mutations'], () => {
-    // require the updated modules
-    // have to add .default here due to babel 6 module output
+    // 获取更新后的模块
+    // 因为 babel 6 的模块编译格式问题,这里需要加上 .default
     const newActions = require('./actions').default
     const newMutations = require('./mutations').default
-    // swap in the new actions and mutations  
-    vuex.hotUpdate({
+    // 加载新模块 
+    store.hotUpdate({
       actions: newActions,
       mutations: newMutations
     })

+ 12 - 12
docs/zh-cn/middlewares.md

@@ -1,6 +1,6 @@
 # 中间件
 
-Vuex 实例可以接受 `middlewares`。中间件给每一个 mutation 暴露勾子(注意和 Redux 的中间件完全没有关系)。一个 Vuex 中间件是一个包含一些勾子函数的简单对象:
+Vuex store 可以接受 `middlewares` 选项来加载中间件。中间件在每一个 mutation 被触发后会调用响应的勾子函数(注意这和 Redux 的中间件概念完全没有关系)。一个 Vuex 中间件即是一个包含一些勾子函数的简单对象:
 
 ``` js
 const myMiddleware = {
@@ -9,38 +9,38 @@ const myMiddleware = {
   },
   onMutation (mutation, state) {
     // 每个 mutation 后会被调用
-    // mutation 在这里会被格式化为 { type, payload }
+    // mutation 参数的格式为 { type, payload }
   }
 }
 ```
 
-可以这样去使用中间件
+使用方式如下
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   // ...
   middlewares: [myMiddleware]
 })
 ```
 
-一个中间件默认会接受一个真实的 `state` 对象,但中间件其实用于 debugging, 他们是 **不允许改变 state 的**
+一个中间件默认会接受到原本的 `state` 对象,但中间件通常用于 debugging 或是数据持久化, 它们是 **不允许改变 state 的。**
 
-有时候中间件想要获得 state 的快照(snapshots),并且用来比较 mutation 前后的 state。这样的中间件必须定义 `snapshot: true` 选项:
+有时候我们可能会想要在中间件中获得 state 的快照(snapshots),用来比较 mutation 前后的 state。这样的中间件必须定义 `snapshot: true` 选项:
 
 ``` js
 const myMiddlewareWithSnapshot = {
   snapshot: true,
   onMutation (mutation, nextState, prevState) {
-    // nextState and prevState are deep-cloned snapshots
-    // of the state before and after the mutation.
+    // nextState 和 prevState 分别为 mutation 触发前
+    // 和触发后对原 state 对象的深拷贝
   }
 }
 ```
 
-**可以获得快照的中间件只能在开发环境下使用**。使用 Webpack 或 Browserify 时,我们可以让 build tools 帮我们处理这个事情
+**可以获得快照的中间件只应在开发环境下使用**。使用 Webpack 或 Browserify 时,我们可以让工具来帮我们处理这个问题
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   // ...
   middlewares: process.env.NODE_ENV !== 'production'
     ? [myMiddlewareWithSnapshot]
@@ -48,14 +48,14 @@ const vuex = new Vuex({
 })
 ```
 
-中间件默认会被使用。在最终的生产环境下,请根据 [这里](http://vuejs.org/guide/application.html#Deploying_for_Production) 把 `process.env.NODE_ENV !== 'production'` 替换为 `false`。
+在开发环境中,中间件默认会被使用。在最终的生产环境下,请根据 [这里提供的配置](http://vuejs.org/guide/application.html#Deploying_for_Production) 把 `process.env.NODE_ENV !== 'production'` 替换为 `false`。
 
 ### 内置的 logger 中间件
 
 Vuex 有个自带的 logger 中间件用于 debugging:
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   middlewares: [Vuex.createLogger()]
 })
 ```

+ 27 - 24
docs/zh-cn/mutations.md

@@ -1,11 +1,11 @@
 # Mutations
 
-Vuex mutations 是必要的 events:每个 mutation 都有一个 **name** 和 一个 **handler**. Handler 的第一个参数为整个 state 树
+Mutations 本质上是一个事件系统:每个 mutation 都有一个 **事件名 (name)** 和 一个 **回调函数 (handler)**. 任何一个 Mutation handler 的第一个参数永远为所属 store 的整个 state 对象
 
 ``` js
 import Vuex from 'vuex'
 
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state: {
     count: 1
   },
@@ -18,19 +18,17 @@ const vuex = new Vuex({
 })
 ```
 
-用大定命名 mutation 是为了将它和 actions 区分开。
+用全部大写命名 mutation 是一个惯例,方便将它和 actions 区分开。
 
-你不能直接调用 mutation handler. 这里的 options 更像是一种事件注册:『当 `INCREMENT` 事件被触发时,调用这个 handler』。引出 mutaion handler 的方法是 dispatch 一个 mutation 事件:
+你不能直接调用 mutation handler. 这里传入 Store 构造函数的选项更像是在注册事件回调:『当 `INCREMENT` 事件被触发时,调用这个 handler』。触发 mutation handler 的方法是 dispatch 一个 mutation 事件
 
 ``` js
-vuex.dispatch('INCREMENT')
+store.dispatch('INCREMENT')
 ```
 
 ### 带参数的 dispatch
 
-It is also possible to pass along arguments:
-
-dispatch 可以带参数:
+`store.dispatch` 可以接受额外的参数:
 
 ``` js
 // ...
@@ -44,20 +42,27 @@ mutations: {
 vuex.dispatch('INCREMENT', 10)
 ```
 
-这里的 `10` 会紧跟着 `state` 作为第二个参数被传递到 mutation handler. 和所有额外的参数一样,这些参数被称为 mutation 的 payload.
+这里的 `10` 会紧跟着 `state` 作为第二个参数被传递到 mutation handler. 所有额外的参数被称为该 mutation 的 payload.
+
+### Mutations 应当遵守 Vue 的响应系统规则
+
+由于 Vuex store 内部的 state 对象被 Vue 改造成了响应式对象,当我们对 state 进行修改时,任何观测着 state 的 Vue 组件都会自动地进行相应地更新。但同时,这也意味着在 Vuex 的 mutation handler 中修改状态时也需要遵循 Vue 特有的一些注意点:
 
-### 遵守 Vue 响应规则的 mutations
+1. 尽可能在创建 store 时就初始化 state 所需要的所有属性;(就像创建 Vue 实例时应当初始化 `data` 一样)
 
-Since Vuex's state is made reactive by Vue, when we mutate the state, Vue components observing the state will update automatically. This also means Vuex mutations are subject to the same reactivity caveats when working with plain Vue:
+2. 当添加一个原本不存在的属性时,需要:
 
-1. Prefer initializing your Vuex initial state with all desired fields upfront.
-2. When adding new properties to an Object, you should either use `Vue.set(obj, 'newProp', 123)`, or replace that Object with a fresh one, e.g. `state.obj = { ...state.obj, newProp: 123 }` (Using stage-2 [object spread syntax](https://github.com/sebmarkbage/ecmascript-rest-spread) here).
+  - 使用 `Vue.set(obj, 'newProp', 123)`;或者 -
 
-???
+  - 拷贝并替换原本的对象。利用 stage 2 的语言特性 [object spread syntax](https://github.com/sebmarkbage/ecmascript-rest-spread),我们可以使用这样的语法:
 
-### 用常量为 mutation 命名
+    ``` js
+    state.obj = { ...state.obj, newProp: 123 }
+    ```
 
-为了可以使 linters 之类的工具发挥作用,通常我们建议使用常量去命名一个 mutation, 并且把这些常量放在单独的地方。这样做可以让你的代码合作者对整个 app 的 mutations 一目了然:
+### 用常量为 Mutations 命名
+
+为了可以使 linters 之类的工具发挥作用,通常我们建议使用常量去命名一个 mutation, 并且把这些常量放在单独的地方。这样做可以让你的代码合作者对整个 app 包含的 mutations 一目了然:
 
 ``` js
 // mutation-types.js
@@ -65,11 +70,11 @@ export const SOME_MUTATION = 'SOME_MUTATION'
 ```
 
 ``` js
-// vuex.js
+// store.js
 import Vuex from 'vuex'
 import { SOME_MUTATION } from './mutation-types'
 
-const vuex = new Vuex({
+const store = new Vuex.Store({
   state: { ... },
   actions: { ... },
   mutations: {
@@ -82,12 +87,10 @@ const vuex = new Vuex({
 })
 ```
 
-用不用常量取决于你 —— 事实上这样做大多数开发者很有帮助。但如果你不喜欢,你完全可以不这样做。
-
-### On to Actions
+用不用常量取决于你 —— 在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。
 
-???
+### 下一步:Actions
 
-手动调用 `vuex.dispatch` 当然可以,但我们很少在组件里这样做,一般我们会调用 [actions](actions.md)。在 actions 里封装着异步数据请求之类的复杂逻辑。
+到目前为止,我们都通过手动调用 `vuex.dispatch` 来触发 mutations。这样做固然可以,但实际上在组件里我们将会很少这样做。一般我们会通过调用 [actions](actions.md) 来触发 mutations。在 actions 里,我们可以封装异步数据请求之类的复杂逻辑。
 
-最后,要记得:所有 mutation handler 必须是 **同步** 的。异步的请求都应在 actions 里。
+最后,切记所有 mutation handler 必须是 **同步** 的。异步的请求都应在 actions 里处理

+ 11 - 11
docs/zh-cn/state.md

@@ -8,45 +8,45 @@ Vuex 使用 **单状态树(single state tree)** —— 也就是单个对象
 
 ### 在 Vue 组件中获得 Vuex State
 
-和 Vue 实例中的 `data` 对像一样,`state` 对象一旦进入 Vuex 实例,就会被 Vue.js 改造成响应式对象(参见 [Vue.js 响应系统](http://vuejs.org/guide/reactivity.html))。因此,要让 Vuex state 来驱动 Vue 组件的渲染,只需要简单地在一个计算属性中返回 Vuex state 中需要的部分即可:
+和 Vue 实例中的 `data` 对像一样,`state` 对象一旦进入 Vuex store,就会被 Vue.js 改造成响应式对象(参见 [Vue.js 响应系统](http://vuejs.org/guide/reactivity.html))。因此,要让 Vuex store 的 state 来驱动 Vue 组件的渲染,只需要简单地在一个计算属性中返回 `store.state` 中需要的部分即可:
 
 ``` js
 // 一个 Vue 组件模块内部
 
-// 引入一个 vuex 实例
-import vuex from './vuex'
+// 引入一个 vuex store 实例
+import store from './store'
 
 export default {
   computed: {
     message () {
-      return vuex.state.message
+      return store.state.message
     }
   }
 }
 ```
 
-我们并不需要建立任何监听器或者用一个 API 去建立组件和 store 之间的联系 - Vue 的响应式系统会确保界面的自动更新。唯一要记住的是,**在计算属性里,必须通过 `vuex.state.xxx` 引用 state**。不要在计算属性外部存放 state 的引用。
+我们并不需要建立任何监听器或者用一个 API 去建立组件和 store 之间的联系 - Vue 的响应式系统会确保界面的自动更新。唯一要记住的是,**在计算属性里,必须通过 `store.state.xxx` 引用 state**。不要在计算属性外部存放 state 的引用。
 
 > Flux 相关:这里计算属性的用法可以和 Redux 的 [`mapStateToProps`](https://github.com/rackt/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) 以及 NuclearJS 的 [getters](https://optimizely.github.io/nuclear-js/docs/04-getters.html) 做类比。
 
-你可能会问为什么我们不直接用 `data` 去绑定 vuex state,我们看以下例子:
+你可能会问为什么我们不直接用 `data` 去绑定 state,我们看以下例子:
 
 ``` js
 export default {
   data () {
     return {
-      message: vuex.state.message
+      message: store.state.message
     }
   }
 }
 ```
 
-因为 `data` 函数不追踪任何响应式依赖, 我们得到的仅仅是一个对 `vuex.state.message` 的静态引用。即使之后 Vuex state 被改变,组件也无法知道它的改变。而计算属性则不同,它在求值时会自动跟踪依赖,因此当状态改变时会自动触发更新。
+因为 `data` 函数不追踪任何响应式依赖, 我们得到的仅仅是一个对 `store.state.message` 的静态引用。即使之后 state 被改变,组件也无法知道它的改变。而计算属性则不同,它在求值时会自动跟踪依赖,因此当状态改变时会自动触发更新。
 
 ### 组件不允许直接改变 state
 
-使用只读的计算属性有一个好处就是,能更好的遵守 **组件永远不能直接改变 Vuex state** 的准则。由于我们希望每一次状态的变动都意图清晰且可被跟踪,因此所有的全局状态变动都必须在 vuex 的 mutation handlers 当中执行。
+使用只读的计算属性有一个好处就是,能更好的遵守 **组件不允许直接改变 store state** 的准则。由于我们希望每一次状态的变动都意图清晰且可被跟踪,因此所有的全局状态变动都必须在 store 的 mutation handlers 当中执行。
 
-为了践行这条准则,在 [严格模式](strict.md) 中如果在 mutation handlers 外部改变 Vuex state,Vuex 会抛出错误。
+为了践行这条准则,在 [严格模式](strict.md) 中如果在 mutation handlers 外部改变 Vuex store state,Vuex 会抛出错误。
 
-根据这条准则,我们的 Vue 组件处理的事情就很少了:它们只需要通过只读的计算属性和 Vuex state 建立联系,而改变 state 的唯一方法就是调用 **actions**. 组件依然能在必要时拥有和操作自己的本地状态,但我们再也不需要在组件里包含任何与全局状态相关的逻辑了。
+根据这条准则,我们的 Vue 组件处理的事情就很少了:它们只需要通过只读的计算属性和 store 内部的 state 建立联系,而改变 state 的唯一方法就是调用 **actions**. 组件依然能在必要时拥有和操作自己的本地状态,但我们再也不需要在组件里包含任何与全局状态相关的逻辑了。

+ 6 - 18
docs/zh-cn/strict.md

@@ -1,36 +1,24 @@
-# Strict Mode
-
 # 严格模式
 
-To enable strict mode, simply pass in `strict: true` when creating the Vuex instance:
-
-要开启严格模式,只需要在创建 Vuex 实例时传入 `strict: true`:
+要开启严格模式,只需要在创建 Vuex store 实例时传入 `strict: true`:
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   // ...
   strict: true
 })
 ```
 
-In strict mode, whenever Vuex state is mutated outside of mutation handlers, an error will be thrown. This ensures that all state mutations can be explicitly tracked by debugging tools.
-
-在严格模式中,每当 Vuex state 在 mutation handlers 外部被改变时都会抛出错误,以确保所有 state mutations 都可以清晰地被 debugging 工具跟踪。
-
-### Development vs. Production
+在严格模式中,每当 Vuex state 在 mutation handlers 外部被改变时都会抛出错误。这样我们可以确保所有对状态的改变都可以清晰地被 debugging 工具所记录。
 
 ### 开发环境 vs. 生产环境
 
-**Do not enable strict mode when deploying for production!** Strict mode runs a deep watch on the state tree for detecting inappropriate mutations - make sure to turn it off in production to avoid the performance cost.
-
-**不要在生产环境中开启严格模式!** 为检测使用有问题的 mutations, 严格模式会对 state 树进行深入的监测。所以为了避免不必要的性能损耗,请在生产环境中关闭严格模式。
-
-Similar to middlewares, we can let the build tools handle that:
+**不要在生产环境中开启严格模式!** 为了检测在不合适的地方发生的状态修改, 严格模式会对 state 树进行一个深观察 (deep watch)。所以为了避免不必要的性能损耗,请在生产环境中关闭严格模式。
 
-和中间件一样,我们可以借助 build tool 来做这件事情
+和配置带快照的中间件一样,我们可以通过配置构建工具来将其自动化:
 
 ``` js
-const vuex = new Vuex({
+const store = new Vuex.Store({
   // ...
   strict: process.env.NODE_ENV !== 'production'
 })

+ 26 - 31
docs/zh-cn/structure.md

@@ -1,13 +1,13 @@
 # 应用结构
 
-Vuex 并非限制你的代码结构,而是遵循一些观点
+Vuex 并不限制你的代码结构,但是制定了一套需要遵守的规则
 
-1. 应用 state 存在于单个对象中
-2. 只有 mutation handlers 可以改变 state
-3. Mutations 必须是同步的,它们做的应该仅仅是改变 state
-4. 所有类似数据获取的异步操作细节都应在 actions 里
+1. 应用 state 存在于单个对象中
+2. 只有 mutation handlers 可以改变 state
+3. Mutations 必须是同步的,它们做的应该仅仅是改变 state
+4. 所有类似数据获取的异步操作细节都应封装在 actions 里面。
 
-Vuex actions 和 mutations 很好的地方在于 **他们都仅仅是函数**。你只需要遵循以上的准则,怎么组织代码就取决于你自己了。最简单的 Vuex 实例甚至只需要在 [单个文件](https://github.com/vuejs/vuex/blob/master/examples/counter/vuex.js) 中声明!然而这对于很多项目来说并不够,所以这里有些根据不同应用规模推荐的不同结构。
+Vuex actions 和 mutations 优雅的地方在于 **它们都只是一些函数**。只需要遵循以上的准则,怎么组织代码就取决于你自己了。最简单的 Vuex store 实例甚至可以在 [单个文件](https://github.com/vuejs/vuex/blob/master/examples/counter/vuex.js) 中声明!然而这在真正的项目里显然是行不通的,所以这里有些根据不同应用规模推荐的不同结构。
 
 ### 简单的项目
 
@@ -20,19 +20,17 @@ Vuex actions 和 mutations 很好的地方在于 **他们都仅仅是函数**。
 ├── components
 │   ├── App.vue
 │   └── ...
-└── vuex
+└── store
     ├── index.js     # exports the vuex instance
     ├── actions.js   # exports all actions
     └── mutations.js # exports all mutations
 ```
 
-一个真实的 [TodoMVC 例子](https://github.com/vuejs/vuex/tree/master/examples/todomvc).
+参见 [TodoMVC 示例](https://github.com/vuejs/vuex/tree/master/examples/todomvc).
 
-### Medium to Large Project
+### 中型到大型项目
 
-### 逐渐复杂的项目
-
-For any non-trivial app, we probably want to further split Vuex-related code into multiple "modules" (roughly comparable to "stores" in vanilla Flux), each dealing with a specific domain of our app. Each module would be managing a sub-tree of the state, exporting the initial state for that sub-tree and all mutations that operate on that sub-tree:
+对于有一定规模的项目,我们会希望把 Vuex 相关的代码分割到多个『模块 (module)』当中去,每一个 module 负责应用的一个领域(和原始 Flux 中的多个 store 类似)。在 Vuex 中,一个模块所要做的其实也就是导出 state 的一部分(可以理解为一颗子树),以及和该部分 state 相关的所有 mutations:
 
 ???
 
@@ -44,7 +42,7 @@ For any non-trivial app, we probably want to further split Vuex-related code int
 ├── components
 │   ├── App.vue
 │   └── ...
-└── vuex
+└── store
     ├── actions.js # exports all actions
     ├── index.js
     ├── modules
@@ -56,13 +54,13 @@ For any non-trivial app, we probably want to further split Vuex-related code int
 一个典型的模块:
 
 ``` js
-// vuex/modules/products.js
+// store/modules/products.js
 import { RECEIVE_PRODUCTS, ADD_TO_CART } from '../mutation-types'
 
-// initial state
+// 该模块的初始状态
 export const productsInitialState = []
 
-// mutations
+// 相关的 mutations
 export const productsMutations = {
   [RECEIVE_PRODUCTS] (state, products) {
     state.products = products
@@ -77,49 +75,46 @@ export const productsMutations = {
 }
 ```
 
-在 `vuex/index.js` 里我们把多个模块集合在一起来创建 Vuex 实例:
+在 `store/index.js` 里我们把多个模块集合在一起来创建 Vuex 实例:
 
 ``` js
 import Vue from 'vue'
 import Vuex from '../../../src'
 import * as actions from './actions'
-// import parts from modules
+// 导入各个模块的初始状态和 mutations
 import { cartInitialState, cartMutations } from './modules/cart'
 import { productsInitialState, productsMutations } from './modules/products'
 
 Vue.use(Vuex)
 
-export default new Vuex({
+export default new Vuex.Store({
   // ...
-  // combine sub-trees into root state
+  // 将各个模块的状态组合成最终的根状态 (root state)
   state: {
     cart: cartInitialState,
     products: productsInitialState
   },
-  // mutations can be an array of mutation definition objects
-  // from multiple modules
+  // mutations 选项可以是一个包含多个对象的数组
   mutations: [cartMutations, productsMutations]
 })
 ```
 
-Since all modules simply export objects and functions, they are quite easy to test and maintain. You are also free to alter the patterns used here to find a structure that fits your preference.
-
-Note that we do not put actions into modules, because a single action may dispatch mutations that affect multiple modules. It's also a good idea to decouple actions from the state shape and the implementation details of mutations for better separation of concerns. If the actions file gets too large, we can turn it into a folder and split out the implementations of long async actions into individual files.
+由于一个模块导出的仅仅是对象和函数,它们也是非常易于测试和维护的。当然,你也可以按你的喜好和需求对这样的组织方式进行修改。
 
-For an actual example, check out the [Shopping Cart Example](https://github.com/vuejs/vuex/tree/master/examples/shopping-cart).
+需要注意的一点:我们并不把 actions 放在模块里面,因为一个 action 可能需要触发影响多个模块的 mutations。同时,actions 本来就应该和具体的状态以及 mutations 解耦。如果单独的 actions 文件变得太过庞大,我们也可以划分出一个 actions 文件夹并将 actions 分散到多个文件中。
 
-???
+参见 [购物车示例](https://github.com/vuejs/vuex/tree/master/examples/shopping-cart)。
 
 ### 提取共用的 Computed Getters
 
-在大型项目中,多个组件使用同一个基于 Vuex state 的 computed 属性是有可能的。由于 computed getters 只是普通函数,你可以把它们独立在另一个文件里,以实现共享:
+在大型项目中,你可能会发现有多个组件使用相似的计算属性来获取 state。由于计算属性的 getters 也只是普通函数,你可以把它们独立出来放在一个单独的文件里,以实现在多个组件之间的共享:
 
 ``` js
 // getters.js
-import vuex from './vuex'
+import store from './store'
 
 export function filteredTodos () {
-  return vuex.state.messages.filter(message => {
+  return store.state.messages.filter(message => {
     return message.threadID === vuex.state.currentThreadID
   })
 }
@@ -136,4 +131,4 @@ export default {
 }
 ```
 
-这非常像 [Getters in NuclearJS](https://optimizely.github.io/nuclear-js/docs/04-getters.html).
+这和 [NuclearJS 中的 Getters 概念](https://optimizely.github.io/nuclear-js/docs/04-getters.html) 非常相似。

+ 19 - 21
docs/zh-cn/testing.md

@@ -1,12 +1,10 @@
 # 测试
 
-Mutations 很容易测试,因为它仅仅是一个带参数的函数。相反测试 Actions 就比较难,因为 actions 会调用其它的一些 APIs. 测试 actions 的时候我们需要做一定的 mocking —— 比如说把 API 调用抽象成一个 service,然后测试的时候用另一个 mock 的 service. 为了方便地 mock,我们可以使用 Webpack 和 [inject-loader](https://github.com/plasticine/inject-loader) 打包测试文件。
+Mutations 很容易测试,因为它仅仅是一个完全依赖参数的函数。相比之下,测试 Actions 会复杂一些,因为 actions 可能会调用一些外部的 API。 测试 actions 的时候我们需要做一定的 mocking —— 比如说把 API 调用抽象成一个 service,然后测试的时候用另一个 mock 的 service. 为了方便地 mock,我们可以使用 Webpack 和 [inject-loader](https://github.com/plasticine/inject-loader) 打包测试文件。
 
-If your mutations and actions are written properly, the tests should have no direct dependency on Browser APIs after proper mocking. Thus you can simply bundle the tests with Webpack and run it directly in Node. Alternatively, you can use `mocha-loader` or Karma + `karma-webpack` to run the tests in real browsers.
+如果你的 mutation 和 action 遵循了 Vuex 的规则,那么在 mock 之后它们应该对浏览器 API 没有任何直接依赖。因此,打包之后的文件可以直接在 Node.js 下运行。如果你想要在真正的浏览器里跑测试,则可以使用 `mocha-loader` 或是 Karma + `karma-webpack` 的组合。
 
-???
-
-下面是用 Mocha + Chai 测试 mutation 的例子(你可以用任何你喜欢的测试工具):
+下面是用 Mocha + Chai 测试一个 mutation 的例子(实际上你可以用任何你喜欢的测试框架):
 
 ``` js
 // mutations.js
@@ -36,7 +34,7 @@ describe('mutations', () => {
 // actions.js
 import shop from '../api/shop'
 
-export const getAllProducts = () => dispatch => {
+export const getAllProducts = ({ dispatch }) => {
   dispatch('REQUEST_PRODUCTS')
   shop.getProducts(products => {
     dispatch('RECEIVE_PRODUCTS', products)
@@ -46,14 +44,13 @@ export const getAllProducts = () => dispatch => {
 
 ``` js
 // actions.spec.js
-
-// use require syntax for inline loaders.
-// with inject-loader, this returns a module factory
-// that allows us to inject mocked dependencies.
 import { expect } from 'chai'
+// 这里因为需要用 webpack loader 所以使用 require() 而不是 import
+// inject-loader 会返回一个工厂函数。这个工厂函数让我们可以对该模块的
+// 依赖进行 mock
 const actionsInjector = require('inject!babel!./actions')
 
-// create the module with our mocks
+// 调用工厂函数,获得 mock 过依赖的 actions 模块
 const actions = actionsInjector({
   '../api/shop': {
     getProducts (cb) {
@@ -64,10 +61,11 @@ const actions = actionsInjector({
   }
 })
 
-// helper for testing action with expected mutations
+// 这是一个可复用的助手函数,用于断言一个 action 应触发的 mutations
 const testAction = (action, state, expectedMutations, done) => {
   let count = 0
-  const mockedDispatch = (name, payload) => {
+  // mock dispatch
+  const dispatch = (name, payload) => {
     const mutation = expectedMutations[count]
     expect(mutation.name).to.equal(name)
     if (payload) {
@@ -78,12 +76,17 @@ const testAction = (action, state, expectedMutations, done) => {
       done()
     }
   }
-  action(mockedDispatch, state)
+  // call the action with mocked store
+  action({
+    dispatch,
+    state
+  })
 }
 
+// 实际测试
 describe('actions', () => {
   it('getAllProducts', done => {
-    testAction(actions.getAllProducts(), {}, [
+    testAction(actions.getAllProducts, {}, [
       { name: 'REQUEST_PRODUCTS' },
       { name: 'RECEIVE_PRODUCTS', payload: [ /* mocked response */ ] }
     ], done)
@@ -124,12 +127,7 @@ webpack
 mocha test-bundle.js
 ```
 
-### 在浏览器运行
-
-1. Install `mocha-loader`
-2. Change the `entry` from the Webpack config above to `'mocha!babel!./test.js'`.
-3. Start `webpack-dev-server` using the config
-4. Go to `localhost:8080/webpack-dev-server/test-bundle`.
+### 在浏览器中运行
 
 1. 安装 `mocha-loader`
 2. webpack 配置中的 entry 改成 `'mocha!babel!./test.js'`