Vuex中mutations和actions的区别及说明
mutation
我们知道,在使用vuex对项目状态进行管理时,只能使用commit来提交mutation对store中的状态进行更改
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
//你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:
store.commit('increment')
Mutation 必须是同步函数
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
我们注意上面这段代码,在mutation里面加入了异步处理的函数。
其实mutation是可以正常使用的,但是我们在日常的开发中debug的时候,我们需要查看devtool中的mutation日志。
理论上来说,是mutation走一步,devtool记录一步,但是在mutation中加入异步函数就会导致我们devtool的记录失败,因为devtool不知道你里面的异步函数什么时候调用,在哪里调用
Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
实践中,我们会经常用到 ES2015 的 参数解构 (opens new window)来简化代码(特别是我们需要调用 commit 很多次的时候):
actions: {
increment ({ commit }) {
commit('increment')
}
}
在实际开发的store文件中
// class="lazy" data-src/store/index.js
import Vue from 'vue';
import Vuex from '@/vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
num: 10
},
getters: {
getPrice(state) {
return state.num * 10
}
},
// 同步更新状态
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
const user = {
state: {
token: getToken(),
name: '',
avatar: '',
roles: [],
permissions: []
},
//同步方法
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
}
},
//异步方法
actions: {
// 登录(使用单点登录此处就作废)
Login({ commit }, userInfo) {
const loginType = userInfo.loginType
const tentantCode = userInfo.tentantCode
const username = userInfo.username.trim()
const password = userInfo.password
const code = userInfo.code
const uuid = userInfo.uuid
return new Promise((resolve, reject) => {
login(loginType, tentantCode, username, password, code, uuid).then(res => {
setToken(res.token)
commit('SET_TOKEN', res.token)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 获取用户信息
GetInfo({ commit, state }) {
return new Promise((resolve, reject) => {
getInfo().then(res => {
if (res.data.rolePermission
&& res.data.rolePermission
> 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_NAME', res.data.nickName
)
commit('SET_AVATAR', res.data.avatar)
resolve(res)
}).catch(error => {
reject(error)
})
})
},
// 退出系统
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
commit('SET_PERMISSIONS', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
}
}
}
export default user
比如我们在登录的时候需要触发store中的方法
<template>
<div>单点登录页面</div>
</template>
<script>
import {
doLoginByTicket,
getInfo,
isLogin,
getSsoAuthUrl,
getRouter,
} from "../api/login";
import { getToken, setToken } from "@/utils/auth";
export default {
name: "Screenfull",
data() {
return {};
},
created() {
this.checkIsLogin();
},
methods: {
checkIsLogin() {
isLogin().then((res) => {
if (res.data == true) {
//获取用户信息;
console.log("isLogin", res);
// this.$router.push("/");
} else {
//获取请求进来的完整url
let url = window.location.href;
if (url.indexOf("ticket=") < 0) {
//如果没有ticket
getSsoAuthUrl({ clientLoginUrl: url }).then((res) => {
window.location.href = res.data;
});
return;
}
let tstr = url
.substring(url.indexOf("?") + 1)
.split("=")[1]
.split("#")[0]; //先截取url的?后面的参数部分,在根据&分割成参数数组
doLoginByTicket({ ticket: tstr }).then((res) => {
if (res.code == 200) {
setToken(res.data);
getInfo().then((res) => {
if (res.data.rolePermission) {
//触发mutations同步方法
this.$store.commit("SET_ROLES", ["admin"]);
this.$store.commit("SET_PERMISSIONS", ["*:*:*"]);
} else {
commit("SET_ROLES", ["ROLE_DEFAULT"]);
}
this.$store.commit("SET_NAME", res.data.nickName);
});
getRouter().then(() => {
//触发actions异步方法
this.$store.dispatch("GenerateRoutes");
window.location.reload();
});
} else {
console.log("检查票据失败");
}
});
}
});
},
},
};
</script>
<style lang="scss" scoped></style>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341