学习用例是在github上找的demo,在原来的基础上学习和总结
源demo地址:https://github.com/lzxb/vue2-demo
里面有安装教程,但是这个demo无法使用es6 的异步方法(会报$export is not a function 错误),需要安装polyfill环境,具体安装和配置的方法如下:
npm install --save @babel/polyfill
安装后需要在webpack.config.js中module.exports中做如下修改
entry: ['@babel/polyfill','./src/main.js'], //编译入口文件
重新启动服务,就可以使用es6了
vuex的流程图如下:
vuex在概念上与react的flux有点类似,由dispach去指派action,action会触发commit调用mutations中的代码,从而改变store中的状态,重要的是vuex的store采用的是模块化的管理,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
这里模块化的管理的意思就是,你可以定义多个js文件,每个js文件中都可以拥有一套去改变store的方法,如项目中的user.js和index.js,他们是嵌套的关系,就是在index中建立全局store,将uesr作为其中的一个模块导入其中,那么就可以直接去调用user中的action,当然这里你可以仿写user.js再定义一些其他的处理函数,导入到index.js中,这样就实现了模块化的管理方式了。
index.js部分代码
modules: {
user
},
这时我们清楚了模块化的定义后再来开始走一下改项目的流程,目的是知道如何去实现vuex的调用过程的
首先是登录界面,这里不再详细说明路由的过程了,可以参考我的上篇博客
在login.vue页面主要js代码
'
在这里主要是引入关键字,声明action,函数dispatch各个action,这里很好理解,注意点是这里有三种调用action的方法,
this.USER_SIGNIN(this.form)//声明action后可直接使用this指针调用,但需要以函数的方式调用
store.dispatch(USER_SIGNIN,this.form)//需要引入store,直接用dispach掉用
this.$store.dispatch(USER_SIGNIN,this.form)//vuex将store挂载到系统中,不需要去引入,可直接使用
下面是各个action的定义user.js
import Vue from 'vue'
export const USER_SIGNIN = 'USER_SIGNIN' //登录成功
export const USER_SIGNOUT = 'USER_SIGNOUT' //退出登录
export default {
state: JSON.parse(sessionStorage.getItem('user')) || {},
mutations: {
[USER_SIGNIN](state, user) {
sessionStorage.setItem('user', JSON.stringify(user))
Object.assign(state, user)
},
[USER_SIGNOUT](state) {
sessionStorage.removeItem('user')
Object.keys(state).forEach(k => Vue.delete(state, k))
}
},
actions: {
[USER_SIGNIN]({commit}, user) {
commit(USER_SIGNIN, user)
},
[USER_SIGNOUT]({commit}) {
commit(USER_SIGNOUT)
}
}
}
这里如果sessionStorage中有user将其取出,放入到state中,action中是标准的模块化的写法(带参和无参),由commit触发mutation中的函数触发对state的修改
登录后的跳转home页面,在页面使用mapstate去获取state的数据赋值到该页面的变量中
首页
退出
{{user.name}}欢迎回家
该页面可以直接使用state的数据
以上就是vuex的流程,很简单,但是里面也有很多东西需要注意,比如mutation中的函数是无法异步的等,如果需要更加细致的说明,点这里
action是可以异步的,所以我们在实际开发中如果需要异步去完成一个很复杂的操作,不妨可以试试异步的action,这里我在index.js中使用了异步的方法,仅供参考
import Vue from 'vue'
import Vuex from 'vuex'
import user from './user'
export const TEST_OUT = 'TEST_OUT' //测试输出
export const actionA = 'actionA' //测试输出
export const actionB = 'actionB' //测试输出
export const actionC = 'actionC' //测试输出
Vue.use(Vuex)
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: '123', done: true },
{ id: 2, text: '456', done: false }
]
},
strict: process.env.NODE_ENV !== 'production', //在非生产环境下,使用严格模式
getters:{
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
},
modules: {
user
},
computed: {
doneTodosCount () {
console.log( this.$store.getters.doneTodos);
}
},
actions:{
[TEST_OUT]({commit}){
commit(TEST_OUT)
},
[actionB]({commit}){
commit(actionB)
},
// 在C中调B,B完成掉A
async [actionC]({dispatch,commit}){
await dispatch('actionB')
commit(actionA)
},
// 在A中调B等B完成时调用C
[actionA]({dispatch,commit}){
return dispatch('actionB').then(()=>{
commit(actionC)
})
}
},
mutations:{
[TEST_OUT](state){
console.log(this.getters.doneTodos);
console.log(state);
},
[actionC](state){
console.log('this is c');
},
[actionB](state){
console.log('this is b');
},
[actionA](state){
console.log('this is a');
}
}
})
参考登录界面的调用方法,我定义了一个按钮去调用该文件的actionA和actionC,actionA使用的是promise的调用方式,而action使用的是es6的async/await异步调用方式,均可以获取到想要的输出。