Vuex中mutations和actions的區(qū)別及說明
mutation
我們知道,在使用vuex對項目狀態(tài)進行管理時,只能使用commit來提交mutation對store中的狀態(tài)進行更改
Vuex 中的 mutation 非常類似于事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)。這個回調(diào)函數(shù)就是我們實際進行狀態(tài)更改的地方,并且它會接受 state 作為第一個參數(shù):
const store = new Vuex.Store({ ? state: { ? ? count: 1 ? }, ? mutations: { ? ? increment (state) { ? ? ? // 變更狀態(tài) ? ? ? state.count++ ? ? } ? } }) //你不能直接調(diào)用一個 mutation handler。這個選項更像是事件注冊:“當(dāng)觸發(fā)一個類型為 increment 的 mutation 時,調(diào)用此函數(shù)。”要喚醒一個 mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit 方法: store.commit('increment') ??
Mutation 必須是同步函數(shù)
mutations: { ? someMutation (state) { ? ? api.callAsyncMethod(() => { ? ? ? state.count++ ? ? }) ? } }
我們注意上面這段代碼,在mutation里面加入了異步處理的函數(shù)。
其實mutation是可以正常使用的,但是我們在日常的開發(fā)中debug的時候,我們需要查看devtool中的mutation日志。
理論上來說,是mutation走一步,devtool記錄一步,但是在mutation中加入異步函數(shù)就會導(dǎo)致我們devtool的記錄失敗,因為devtool不知道你里面的異步函數(shù)什么時候調(diào)用,在哪里調(diào)用
Action
Action 類似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作。
const store = new Vuex.Store({ ? state: { ? ? count: 0 ? }, ? mutations: { ? ? increment (state) { ? ? ? state.count++ ? ? } ? }, ? actions: { ? ? increment (context) { ? ? ? context.commit('increment') ? ? } ? } })
Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調(diào)用 context.commit 提交一個 mutation,或者通過 context.state 和 context.getters 來獲取 state 和 getters。
實踐中,我們會經(jīng)常用到 ES2015 的 參數(shù)解構(gòu) (opens new window)來簡化代碼(特別是我們需要調(diào)用 commit 很多次的時候):
actions: { ? increment ({ commit }) { ? ? commit('increment') ? } }
在實際開發(fā)的store文件中
// 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 ? ? } ? }, ? // 同步更新狀態(tài) 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是否是一個非空數(shù)組 ? ? ? ? ? ? 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) ? ? ? ? }) ? ? ? }) ? ? }, ? ? // 退出系統(tǒng) ? ? 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
比如我們在登錄的時候需要觸發(fā)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的?后面的參數(shù)部分,在根據(jù)&分割成參數(shù)數(shù)組 ? ? ? ? ? doLoginByTicket({ ticket: tstr }).then((res) => { ? ? ? ? ? ? if (res.code == 200) { ? ? ? ? ? ? ? setToken(res.data); ? ? ? ? ? ? ? getInfo().then((res) => { ? ? ? ? ? ? ? ? if (res.data.rolePermission) { ? ? ? ? ? ? ? ? //觸發(fā)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(() => { ?? ??? ??? ??? ?//觸發(fā)actions異步方法 ? ? ? ? ? ? ? ? this.$store.dispatch("GenerateRoutes"); ? ? ? ? ? ? ? ? window.location.reload(); ? ? ? ? ? ? ? }); ? ? ? ? ? ? } else { ? ? ? ? ? ? ? console.log("檢查票據(jù)失敗"); ? ? ? ? ? ? } ? ? ? ? ? }); ? ? ? ? } ? ? ? }); ? ? }, ? }, }; </script> <style lang="scss" scoped></style>
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
element?ui中el-form-item的屬性rules的用法示例小結(jié)
這篇文章主要介紹了element?ui中el-form-item的屬性rules的用法,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-07-07解決vue v-for 遍歷循環(huán)時key值報錯的問題
今天小編就為大家分享一篇解決vue v-for 遍歷循環(huán)時key值報錯的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vuex中mutations與actions的區(qū)別詳解
下面小編就為大家分享一篇Vuex中mutations與actions的區(qū)別詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03vue生成二維碼QR?Code的簡單實現(xiàn)方法示例
這篇文章主要為大家介紹了vue生成二維碼QR?Code的實現(xiàn)示例詳情,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04