vuex初识

为什么要引入 vuex?

vuex是什么?

vuex怎么使用?

1.vuex简介

vuex是vue的一个插件(它并没有遵循一般vue插件的命名规范), 它的目的是对vue应用中多个组件的共享状态进行集中式的管理(读/写).

vue是一个状态自管理应用. 下面是整个vue应用的数据流通图:

Vue5-1.1

State: 驱动整个应用的数据源.

View: 以声明方式将State中的数据映射到视图.

Actions: 响应在View上的用户输入导致的状态变化(包含多种更新状态的方法)

关于多组件共享状态

产生的问题:

  • ①多个视图依赖于同一状态.
  • ②来自不同视图的行为需要变更同一状态.

之前的解决方法:

  • a. 将数据及操作数据的行为都定义在父组件里
  • b. 将数据及操作数据的行为传递给需要的各个组件(可能存在多级传递)

而vuex就是用来专门解决这一问题的.

vuex的流程图

Vue5-1.2

2.一个简单的vue计数应用

先使用原始的vue方式实现, 之后一步步改为vuex实现方式.

App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<template>
<div>
<p>click {{count}} times, count is {{evenOrOdd}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">increment if odd</button>
<button @click="incrementAsync">increment async</button>
</div>
</template>

<script>
export default {
data () {
return {
count: 0
}
},
computed: {
evenOrOdd () {
return this.count % 2 === 0 ? '偶数' : '奇数'
}
},
methods: {
increment () {
const count = this.count
this.count = count + 1
},
decrement () {
const count = this.count
this.count = count - 1
},
incrementIfOdd () {
const count = this.count
if (count % 2 === 1) {
this.count = count + 1
}
},
incrementAsync () {
const count = this.count
setTimeout(() => {
this.count = count + 1
}, 1000)
}
}
}
</script>

<style scoped>

</style>

3.vuex的初步使用

  • ①之前项目没有vuex库的需要先安装库: npm install --save vuex
  • ②在项目根目录下创建 store.js, vuex的核心管理对象模块. 编写vuex的核心代码
  • ③将store模块配置到当前项目中: 在main.js中配置store

main.js:

1
2
3
4
5
6
7
8
9
10
11
12
import Vue from 'vue'
import App from './App'
import store from './store'

new Vue({
el: '#app',
components: {
App
},
template: '<App/>',
store// 配置store后,所有组件对象都多了一个属性对象: $store
})

$store 对象

配置完 store 后, 所有的组件对象就都多了一个属性对象: $store, 可以用它来实现很多功能.

$store中有两个属性对象: state 和 getters, 也有方法: dispatch(actionName, data) //用来分发调用actions

App.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<div>
<p>click {{count}} times, count is {{evenOrOdd}}</p>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementIfOdd">increment if odd</button>
<button @click="incrementAsync">increment async</button>
</div>
</template>

<script>
import {mapState, mapActions} from 'vuex'
export default {
computed: {
...mapState(['count']),
evenOrOdd () {
//这里其实是返回了一个vuex的计算属性(可以理解为返回了一个方法)
return this.$store.getters.evenOrOdd
}
},
methods: {
increment () {
this.$store.dispatch('increment')
},
decrement () {
this.$store.dispatch('decrement')
},
...mapActions(['incrementIfOdd', 'incrementAsync'])
}
}
</script>

<style scoped>

</style>

store.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/*
vuex的核心管理对象模块: store
*/
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const mutations = {
INCREMENT (state) {
state.count++
},
DECREMENT (state) {
state.count--
}
}
const actions = {
increment ({commit}) {
commit('INCREMENT')
},
decrement ({commit}) {
commit('DECREMENT')
},
incrementIfOdd ({commit, state}) {
if (state.count % 2 === 1) {
commit('INCREMENT')
}
},
incrementAsync ({commit, state}) {
setTimeout(() => {
commit('INCREMENT')
}, 1000)
}
}
const getters = {
evenOrOdd (state) {
return state.count % 2 === 0 ? '偶数' : '奇数'
}
}
export default new Vuex.Store({
state, // 包含多个状态对象
mutations, // 包含多个更新state函数的对象
actions, // 包含多个对应时间回掉函数的对象
getters// 包含多个getter计算属性函数的对象
})

这个例子并不适合用vuex来做, vuex是用来解决多组件共享状态问题的. 在这里仅仅用来说明vuex的基本语法.

在真正开发一个项目时, 要综合分析, 有时多组件共享问题用vuex实现也不是很好.

4.vuex的一般项目结构

上面的例子中, 将vuex相关的所有代码, 书写在了一个文件(store.js)中. 但在一般大中型项目中, 会将 vuex 的store.js 拆分为五个文件: index.js、actions.js、getters.js、mutations.js、types.js

  • index.js: 创建 state 状态对象, 并将其余几个文件引入后, 向外暴露 store 对象.
  • actions.js: 包含多个事件回调函数的对象, 经常用来做一些异步操作(向服务器请求数据等), 之后通过触发 mutations.js 中的方法, 间接的更新 state .
  • getters.js: vuex的 state 相关的一些计算属性.
  • mutations.js: 包含多个直接更新 state 的方法(回调函数)的对象. 这些方法由 actions.js 中的 commit(‘mutation名’) 触发执行. 注意: 在这里只能执行一些同步代码, 一般只用来同步操作 state .
  • types.js: 创建并向外暴露一些对应 mutations.js 方法的字符串常量.

vuex 还有一种 modules 配置, 但是一般用不到. 在一些状态非常非常多的应用中才会使用.


评论