1. 定义
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
通过官方文档提供的流程图我们知道,vuex的工作流程
1、数据从state中渲染到页面;
2、在页面通过dispatch来触发action;
3、action通过调用commit,来触发mutation;
4、mutation来更改数据,数据变更之后会触发dep对象的notify,通知所有Watcher对象去修改对应视图(vue的双向数据绑定原理)。
应用场景:
- 多个视图依赖于同一状态
- 来自不同视图的行为需要改变同一个状态
vuex的组成介绍
-
State: 数据仓库
-
Getter: 用来获取数据的
-
Mutation: 用来修改数据的
-
Action: 用来提交mutation
-
Module: 模块化store
流程图
2. 安装步骤
- 安装
vuex包npm i vuex --save - 创建
vuex实例:new Vuex.store() - main.js中将vuex实例挂载到vue对象上
3. 引用
- 在main.js的同级目录下新建store文件夹。 store文件夹下新建index.js。 以下为index.js中用来引入vuex的代码
import Vue from 'vue' // 引入vue
import Vuex from 'vuex' // 引入vuex
Vue.use(Vuex)
// 使用 vuex 实例
const store = new Vuex.Store({
state: {
count: 121
},
getters : {
newCount (state) {
return state.count + 100
}
},
mutations: {
numAdd(state, num) {
state.count += num
}
},
actions: {
deleteNum({ commit }, num) {
setTimeout(() => {
commit('numAdd', num)
}, 2000)
}
}
})
export default store // 导出store
- 在main.js中引入store文件夹下的index.js文件
import Vue from 'vue'
import App from './App'
import store from './store' // 主要是这一行
new Vue({
el: '#app',
store, // 还有这一行
render: h => h(App)
})
4.vuex中常用方法和属性的调用
// 方法1 需要引入store import store from '@/store'
store.state.count
// 方法2(需要使用vue.use注入)
this.$store.state.count
// 方法3,通过辅助函数mapState
import { mapState } from 'vuex';
export default {
computed: {
// 使用ES6的扩展运算符来达到将state释放出来
...mapState([
// 映射 this.count 为 store.state.count
'count'
])
}
}
state
<div>这里是store的state--->{{this.$store.state.count}}</div>
const state = {
name: 123456,
greatToken: ''
}
mutations(通过commit触发,一般处理同步操作)
vuex为什么不能直接操作实例化state。而是先通过commit一个mutations函数,然后再改变state的值呢?
答案: 因为每次提交mutations都会有一个记录, 更方便的记录每个记录改变的历史, 方便vue中的回滚,历史的操作
// 定义
CHANGE_NAME: (state,name) => {
state.name = name;
}
// 使用 注意如果是封装成了modules,还需要加上例如 greatwall 这样的路径
this.$store.commit('greatwall/CHANGE_NAME','andy凌云')
actions(通过dispatch触发,一般处理异步操作)
// 定义: 其中CHANGE_NAME是mutations中定义的函数, view是传递的值
const actions = {
changeName({commit, state}, view){
commit('CHANGE_NAME', view)
}
}
// 使用 注意如果是封装成了modules,还需要加上例如 greatwall 这样的路径
this.$store.dispatch('greatwall/changeName','andy')
getters(一般处理异步事件)
- 直接在store中写getters的方式
<div>
这里是store的getter---->{{this.$store.getters.newCount}}
</div>
// 定义
const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
}
export default getters
//使用
return this.$store.getters.roles
- 将getters单独提取出来写getters.js的方式
export default {
memberInfo(state) {
if(state.userStatus === 0) {
return "普通会员"
} else if (state.userStatus === 1){
return "vip会员"
} else if(state.userStatus === 2) {
return `高级${state.vipLevel}会员`
} else {
return "普通会员"
}
}
}
5. 将v-model的值和vuex中的数据绑定上
<input v-model="message">
computed: {
message: {
get () {
return this.$store.state.obj.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
}
- 将各个功能注册到一个store下的index.js中
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
state,
mutations,
actions,
getters
})
export default store;
6. 解决刷新vuex的state状态就丢失的问题
可以在App.vue中进行处理。 添加
beforeunload回调。 每次页面刷新时,将vuex里的信息保存在sessionStorege中。
created() {
this.init();
},
methods: {
init() {
//在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem("store")) {
this.$store.replaceState(Object.assign({}, this.$store.state, JSON.parse(sessionStorage.getItem("store"))))
}
//在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload", () => {
sessionStorage.setItem("store", JSON.stringify(this.$store.state))
})
}
}