Vuex 使用和进阶
安装
在根目录添加 store/index.js
1 2 3 4
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
|
在 main.js
中引入
1 2 3 4 5 6 7 8
| import Vue from 'vue' import App from './App.vue' import store from './store'
new Vue({ store, render: h => h(App) }).$mount('#app')
|
运行原理
首先来看一下vuex的运行原理图

- Vue Components 使我们的组件,组件会触发(dispatch)一些事件或动作(Actions)
- 我们在组件中触发动作肯定是想获取Vuex中数据或者改变Vuex中的数据,但是数据是集中管理的,不能直接被修改。所以我们把这个动作提交(Commit)到Mutations 中
- 然后 Mutations 去修改(Mutate)State 中的数据
- 当 State 中的数据发生变化时会重新渲染(Render) 组件
核心方法
Vuex的核心是 store(仓库),相当于一个容器。一个 Store 的实例中有如下几个属性:
- state:定义属性(状态、数据)
- getters:用来获取数据
- actions:用来定义动作,动作中编写了如何改变state中的数据
- commit:提交变化,处理状态的改变
- mutations:定义变化,处理数据的改变
- mapGetters:用来获取数据
- mapActions:用来获取方法
读取数据
首先编写数据,往 store/index.js
中写入代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const state = { name: '张三' }
export default new Vuex.Store({ state })
|
方式一:
直接通过 this.$roter.state.name
来获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <template> <div> // 页面渲染出来是 张三 {{ $store.state.name }} </div> </template>
<script> export default { data() { return {} }, mounted() { console.log(this.$store.state.name) } } </script>
|
方式二:
通过vuex提供的 mapGetters
来获取数据。在 store/index.js
中编写 getters
并导出

然后再页面中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <template> <div> <div>{{ $store.state.name }}</div> <div>{{ name }}</div> </div> </template>
<script> import { mapGetters } from 'vuex' export default { data() { return {} }, computed: { ...mapGetters(['name']) }, mounted() { console.log(this.$store.state.name) } } </script>
|
修改数据
这里我们使用是在 actions 中通过 commit 的方式来修改数据,这是为了更好的追踪状态变化。也是官方推荐的做法
在 store/index.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
| import Vue from 'vue' import Vuex from 'vuex'
Vue.use(Vuex)
const state = { count: 0 }
const getters = { count(state) { return state.count } }
const actions = { addCount({ commit }) { commit("addCountFun") } }
const mutations = { addCountFun(state) { state.count++ } }
export default new Vuex.Store({ state, getters, actions, mutations })
|
然后再页面中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <template> <div> <div>{{ count }} - {{ $store.state.count }}</div> <el-button type="success" @click="addCount">增加</el-button> </div> </template>
<script>
import { mapGetters, mapActions } from 'vuex' export default { data() { return {} }, computed: { ...mapGetters(['count']) }, methods: { ...mapActions(['addCount']) } } </script>
|
在 actions 中添加逻辑判断
现在我们要添加一个count–的方法,但是当count小于5时不能在减
添加如下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const actions = { subCount({ commit, state }) { if (state.count > 5) { commit("subCountFun") } } }
const mutations = { subCountFun(state) { state.count-- } }
|
效果演示

在 actions 中添加异步事件
在 actions 中添加如下方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| const actions = { asyncAddCount({ commit }) { let addcount = new Promise((resolve) => { setTimeout(() => { resolve() }, 1000) }) addcount.then(() => { commit("addCountFun") }) } }
|
效果演示

读取数据状态
通过在 getters 中添加代码的方式
1 2 3 4 5 6 7 8 9 10 11
| const state = { evenOrOdd:'' }
const getters = { evenOrOdd(state){ return state.count % 2 === 0 ? '偶数' : '奇数' } }
|
效果演示

使用模块化
当我们项目比较复杂时,把所有的数据都写在一个文件中是一件很痛苦的事情。我们可以吧不同的逻辑数据分到不同的文件中去,然后由 index 来统一管理。这样日常的使用和维护都会好很多。
先来一张官方推荐的项目结构

我们按照上图所示,修改现有的文件结构,我们只保留一个 index.js 和 getters.js 文件

- index.js 用来做文件整合并导出 store 实例
- getters.js 用来导出各个 modules 中定义的属性,这样避免 modules 中的属性定义重名问题
首先编写 user.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
| const state = { name: '张三', count: 0, }
const actions = { addCount({ commit }, arg) { commit("addCountFun", arg) }, subCount({ commit, state }) { if (state.count > 5) { commit("subCountFun") } }, asyncAddCount({ commit }) { let addcount = new Promise((resolve) => { setTimeout(() => { resolve() }, 1000) }) addcount.then(() => { commit("addCountFun", 1) }) } }
const mutations = { addCountFun(state, arg) { state.count += arg }, subCountFun(state) { state.count-- } }
export default { namespaced: true, state, actions, mutations }
|
order.js
1 2 3 4 5 6 7 8
| const state = { count: 1241434123213 }
export default { namespaced:true, state }
|
getters.js
1 2 3 4 5 6
| export default { name: state => state.user.name, count: state => state.user.count, evenOrOdd: state => state.user.count % 2 === 0 ? '偶数' : '奇数', o_count:state=>state.order.count }
|
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import Vue from "vue" import Vuex from "vuex" import getters from "./getters" import user from "./modules/user" import order from "./modules/order" Vue.use(Vuex)
export default new Vuex.Store({ getters, modules: { user, order } })
|
在页面中使用方法
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
| <template> <div> <div>{{ $store.state.user.count }}</div> <div>{{ count }} - {{ evenOrOdd }} - {{ name }}</div> <div>order : {{ o_count }}</div> <el-button type="success" @click="addCount"> 增加 </el-button> <el-button type="warning" @click="subCount">减少</el-button> <el-button type="info" @click="asyncAdd">异步增加</el-button> <el-button type="primary" @click="changeOrder"> 改变order中的count </el-button> </div> </template>
<script> import { mapGetters } from 'vuex' import store from '../store' export default { data() { return {} }, computed: { ...mapGetters(['evenOrOdd', 'count', 'name', 'o_count']) }, mounted() { console.log(this.$store.state.user.name) }, methods: { addCount() { store.dispatch('user/addCount', 20) }, subCount() { store.dispatch('user/subCount') }, asyncAdd() { store.dispatch('user/asyncAddCount') }, changeOrder() { store.dispatch('order/setCount', 123456) } } } </script>
|
store.dispatch
派发一个方法,第一个参数为要调用的方法名,第二个参数为要传递的数据
this.$store.state.模块名.属性名
也可以直接使用这种方式读取模块中的数据
最后来查看效果

持久化保存vuex数据
默认 vuex 中的数据刷新页面后会重置,我们想要刷新页面不丢失数据怎么做呢?这里使用 vuex-persistedstate 来实现
安装
1
| npm install --save vuex-persistedstate
|
使用,在 store/index.js
中使用

配置完成后,数据默认会以 localStorage 缓存起来。我们可以打开页面查看 localStorage ,缓存的 key 是 vuex

效果演示,刷新页面后数据不会丢失

如果确实想重置vuex数据,可以通过清理缓存的方式来处理
1
| localStorage.removeItem("vuex")
|