Skip to content

Commit 0302e85

Browse files
mondaychenyyx990803
authored andcommitted
docs/zh-cn/tutorial.md (#167)
* "Table of Contents" to Chinese * add tutorial in zh-cn * Translate tutorial into Chinese * translate vuex flow image * use upper case V following upstream changes * better format in zh-cn/tutorial.md
1 parent ed5efde commit 0302e85

File tree

4 files changed

+267
-1
lines changed

4 files changed

+267
-1
lines changed

docs/zh-cn/SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
# Table of Contents
1+
# 目录
22

33
> 注意:中文版文档目前只更新到 0.2.x 版本,最新版本的文档请看英文版。
44
55
- [什么是 Vuex?](intro.md)
66
- [快速开始](quickstart.md)
7+
- [教程](tutorial.md)
78
- [核心概念](concepts.md)
89
- [State](state.md)
910
- [Mutations](mutations.md)

docs/zh-cn/tutorial.md

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# 教程
2+
3+
让我们通过一个简单的实际例子来理解怎样使用 Vuex。这个例子里,我们要实现一个按钮,当你点击它的时候,计数器会加一。
4+
5+
![End Result](tutorial/result.png)
6+
7+
通过这个简单的例子,我们会解释相应的概念,以及 Vuex 所要解决的问题:如何管理一个包含许多组件的大型应用。假设这个例子使用了以下三个组件:
8+
9+
### `components/App.vue`
10+
11+
根组件,它包含了以下两个子组件:
12+
13+
* `Display` 显示计数器当前的值
14+
* `Increment` 使计数器加一的按钮
15+
16+
```html
17+
<template>
18+
<div>
19+
<Display></Display>
20+
<Increment></Increment>
21+
</div>
22+
</template>
23+
24+
<script>
25+
26+
import Display from './Display.vue'
27+
import Increment from './Increment.vue'
28+
29+
export default {
30+
components: {
31+
Display: Display,
32+
Increment: Increment
33+
}
34+
}
35+
</script>
36+
```
37+
38+
### `components/Display.vue`
39+
40+
```html
41+
<template>
42+
<div>
43+
<h3>Count is 0</h3>
44+
</div>
45+
</template>
46+
47+
<script>
48+
export default {
49+
}
50+
</script>
51+
```
52+
53+
### `components/Increment.vue`
54+
55+
```html
56+
<template>
57+
<div>
58+
<button>Increment +1</button>
59+
</div>
60+
</template>
61+
62+
<script>
63+
export default {
64+
}
65+
</script>
66+
```
67+
68+
### Vuex 要解决的问题
69+
70+
* `Increment``Display` 彼此独立, 不能直接相互传递信息。
71+
* `App` 只能通过事件和广播去整合这两个组件。
72+
* 因为 `App` 需要整合这两个组件,它们无法被重用,形成了紧密的互相依赖。如果需要重构它,容易导致应用的 bug。
73+
74+
### Vuex 的流程
75+
76+
我们需要依次执行这些步骤:
77+
78+
![Vuex Flow](tutorial/vuex_flow.png)
79+
80+
仅仅为了增加计数采取这么多步骤似乎有点多余。但是,这些概念的引入使得我们在大型应用里可以有效提高可维护性,在长期来看也可以使得 debug 和做后续改进工作变得更容易。那么接下来我们就用 vuex 来改写我们的代码:
81+
82+
### 第一步:加入 store
83+
84+
store 存储应用所需要的所有数据。所有组件都会从 store 中读取数据。在我们开始之前,用 npm 安装 Vuex:
85+
86+
```
87+
$ npm install --save vuex
88+
```
89+
90+
建一个新文件 `vuex/store.js`
91+
92+
```js
93+
import Vue from 'vue'
94+
import Vuex from 'vuex'
95+
96+
// 告诉 vue “使用” vuex
97+
Vue.use(Vuex)
98+
99+
// 创建一个 object 存储应用启动时的状态
100+
const state = {
101+
// TODO: 设置启动状态
102+
}
103+
104+
// 创建一个 object 存储 mutation 函数
105+
const mutations = {
106+
// TODO: set up our mutations
107+
}
108+
109+
// 通过 new Vuex.Store 结合初始 state 和 mutations,创建 store
110+
// 这个 store 将和我们的 vue 应用链接起来
111+
export default new Vuex.Store({
112+
state,
113+
mutations
114+
})
115+
```
116+
117+
我们需要修改根组件来让我们的应用和 store 建立联系。
118+
119+
修改 `components/App.vue`,加上 store.
120+
121+
```js
122+
import Display from './Display.vue'
123+
import Increment from './IncrementButton.vue'
124+
import store from '../vuex/store' // import 我们刚刚创建的 store
125+
126+
export default {
127+
components: {
128+
Display: Display,
129+
Increment: Increment
130+
},
131+
store: store // 在根组件加入 store,让它的子组件和 store 连接
132+
}
133+
```
134+
135+
> **提示**: 如果使用 ES6 和 babel 你可以这样写:
136+
>
137+
> components: {
138+
> Display,
139+
> Increment,
140+
> },
141+
> store
142+
143+
### 第二步:创建 action
144+
145+
action 是给 component 使用的函数。action 函数能够通过 dispatch 对应的 mutation 函数来触发 store 的更新。action 也可以从后端读取数据之后再触发更新。
146+
147+
创建一个新文件 `vuex/actions.js`,然后写入一个函数 `incrementCounter`
148+
149+
150+
```js
151+
// action 会收到 store 作为它的第一个参数
152+
// 在 store 里我们只需要 dispatch (在有些情况下需要 state)
153+
// 我们可以利用 ES6 的解构(destructuring)语法来简化参数的使用
154+
export const incrementCounter = function ({ dispatch, state }) {
155+
dispatch('INCREMENT', 1)
156+
}
157+
```
158+
159+
然后我们从 `components/Increment.vue` 组件里调用 action 函数
160+
161+
```
162+
<template>
163+
<div>
164+
<button @click='increment'>Increment +1</button>
165+
</div>
166+
</template>
167+
168+
<script>
169+
import { incrementCounter } from '../vuex/actions'
170+
export default {
171+
vuex: {
172+
actions: {
173+
increment: incrementCounter
174+
}
175+
}
176+
}
177+
</script>
178+
```
179+
180+
回顾一下我们刚刚写的一些有趣的东西:
181+
182+
1. 我们有了一个新的 object `vuex.actions`,包含着一个新的 action。
183+
2. 我们没有指定 store, object, state 等等的东西。Vuex 会把它们串联好。
184+
3. 我们可以使用 `this.increment()` 在任何方法里调用 action。
185+
4. 我们也可以用 `@click` 参数,像使用普通的 Vue 组件方法一样使用它。
186+
5. 我们给 action 起名叫 `incrementCounter`,但是在使用时我们可以根据需要重新命名它。
187+
188+
### 第三步:创建 state 和 mutation
189+
190+
在我们的 `vuex/actions.js` 文件里我们 dispatch 了一个叫做 `INCREMENT` 的 mutation,但是我们还没有写它所对应的具体操作。我们现在就来做这个事。
191+
192+
修改 `vuex/store.js`
193+
194+
```js
195+
const state = {
196+
// 应用启动时,count 置为0
197+
count: 0
198+
}
199+
200+
const mutations = {
201+
// mutation 的第一个参数是当前的 state
202+
// 你可以在函数里修改 state
203+
INCREMENT (state, amount) {
204+
state.count = state.count + amount
205+
}
206+
}
207+
```
208+
209+
### 第四步:在组件获取值
210+
211+
创建一个新的文件 `vuex/getters.js`
212+
213+
```js
214+
// 这个 getter 函数会返回 count 的值
215+
// 在 ES6 里你可以写成:
216+
// export const getCount = state => state.count
217+
218+
export function getCount (state) {
219+
return state.count
220+
}
221+
```
222+
223+
这个函数返回了 state 对象里我们所需要的部分—— count 的值。我们现在在组件里加入这个 getter 函数。
224+
225+
修改 `components/Display.vue`
226+
227+
```html
228+
<template>
229+
<div>
230+
<h3>Count is {{ counterValue }}</h3>
231+
</div>
232+
</template>
233+
234+
<script>
235+
import { getCount } from '../vuex/getters'
236+
export default {
237+
vuex: {
238+
getters: {
239+
// 注意在这里你需要 `getCount` 函数本身而不是它的执行结果 'getCount()'
240+
counterValue: getCount
241+
}
242+
}
243+
}
244+
</script>
245+
```
246+
247+
这里我们又加入了一个新的对象 `vuex.getters`。它将 `counterValue` 绑定到了 `getCount` 这个 getter 函数上。我们给它起了一个新名字来使得这个变量在你的组件里表意更明确。
248+
249+
你可能有点困惑——为什么我们需要用 getter 函数而不是直接从 state 里读取数据。这个概念更多的是一种最佳实践,在大型应用里更加适用。它有这么几种明显的优势:
250+
251+
1. 我们可能需要使用 getter 函数返回经过计算的值(比如总数,平均值等)。
252+
2. 在大型应用里,很多组件之间可以复用同一个 getter 函数。
253+
3. 如果这个值的位置改变了(比如从 `store.count` 变成了 `store.counter.value`),你只需要改一个 getter 方法,而不是一堆用到它的组件。
254+
255+
以上便是使用 getter 带来的好处。
256+
257+
### 第五步:接下来……
258+
259+
运行一下你的应用,它应该能正常工作了。
260+
261+
要更深入地理解 Vuex,你可以做一个小练习:尝试对这个应用做一些修改。
262+
263+
* 加上“减一”的按钮。
264+
* 安装 [VueJS Devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd),尝试使用它提供的 Vuex 工具来观察 mutation 对 state 的改动。
265+
* 加上一个新的组件,让用户可以在文本框中输入要增加的数值。这个会稍有难度,因为在 vuex 架构中表单的处理有些不同。在开始前可以先读一下[表单处理](forms.md)

docs/zh-cn/tutorial/result.png

117 KB
Loading

docs/zh-cn/tutorial/vuex_flow.png

274 KB
Loading

0 commit comments

Comments
 (0)