vuex 的引入放在的是main.js入口文件,然后在构建实例处挂载,也就是说,store这个文件在所有的页面都可以使用,就相当于组件的router 一样,路由可以通过this.$router访问,那么store 也可以通过this.$store.state访问数据;
可以在store文件夹下面建立action,mutation,和modules文件夹,亦可以只建立modules文件夹,然后文件夹里再建立文件,细分文件的归属;同时你也可以这样,直接把文件分为state.js,cation.js,mutation.js,不过这样的话一个数据的更改要跑几个文件夹,有点麻烦,vue2升级vue3也有提到这种麻烦,所以推荐在modules文件夹下的某一个文件夹内写完所有然后导出
这是一个文件夹内的结构,state 是数据,相当于data,getter是计算属性,actions异步提交dispatch,其实也是提交到mutation,只不过是异步的,mutation是同步的commit,注意命名规范,提交的命名是全部大写,可以小写
import { resetRouter } from '@/router';
import { getToken, removeToken, removeAuthorization } from '@/utils/auth';
import { getAccount, setAccount, removeAccount } from '@/utils/account';
import { loginByUsername, logout } from '@/api/account';
import store from '@/store';
const user = {
state: {
account: getAccount(),
token: getToken() || '',
},
getters: {
account: state => state.account,
token: state => state.token,
},
actions: {
// 用户名登录
loginByUsername({ commit }, account) {
return new Promise(async (resolve, reject) => {
try {
const res = await loginByUsername(account);
if (res.success) {
commit('SET_ACCOUNT', res.data);
setAccount(res.data);
// setToken(res.data.token || '');
// commit('SET_TOKEN', data.token || '');
resolve(res);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
});
},
// 退出登录
logout({ commit }, isExpiration = false) {
return new Promise(async (resolve) => {
try {
if (!isExpiration) {
// 非会话过期, 即为主动退出登录, 需发请求
const res = await logout();
console.log('logout res', res);
}
commit('SET_TOKEN', '');
commit('SET_ACCOUNT', null);
// 初始化store中菜单
commit('SET_MENUS', []);
commit('SET_AUTH_LIST', []);
commit('SET_IS_GET_MENU', false);
// 清除字典数据
commit('CLEAR_ALL_DICTIONARY_STATE_MUTATIONS');
store.dispatch('delAllViewsToOther');
removeToken();
removeAuthorization();
removeAccount();
resetRouter();
resolve();
} catch (error) {
console.log('logout error', error);
}
});
},
},
mutations: {
SET_ACCOUNT: (state, account) => {
state.account = account;
},
SET_TOKEN: (state, token) => {
state.token = token;
},
},
};
export default user;
注意mutation的方法,接收的参数,第一个是state,第二个是替换的参数,改变state数据只能通过mutation来更改;
说一下action的方法和mustation 方法
// 方法一:mutation ,通过context 上下文触发事件,payload 是承载
export const saveDbSource = (context, payload) => {
context.commit('saveDbSource', payload);
};
// 方法二:action,通过commit,第二个参数都是payload,这是为了保存数据,不然vuex的数据就是空值
export const saveDbSource = ({ commit }, payload) => {
commit('saveDbSource', payload);
};
vuex的数据更改的使用:
页面中定义方法,点击就触发,然后点击触发的是提交到mutation的方法和挟带修改的参数、
<template> <div> <p>当前最新的count值为:{{$store.state.count}}</p> <button @click="handleAdd">+1</button> //这里的handleAdd是触发的方法 </div> </template> <script> // import {mapState} from 'vuex' export default { name: 'addition', components: {}, data () { return { } }, methods:{ handleAdd(){ this.$store.commit('add',1) // 点击方法体handleAdd,触发提交store的add方法,add是store的方法 } }, // computed: { // ...mapState(['count']) // } } </script> <style scoped> </style> store.js的方法: import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 0 }, mutations: { // 注意方法的参数接收两个参数,一个state 一个是传进来的参数 add(state,num){ state.count= state.count+ num }, del(state,num){ if(state.count >0){ state.count=state.count-num; }else{ state.count =0 } } }, actions: { }, modules: { } })
同时可以用辅助函数来分发数据,其实原理是挺简单的,写在计算属性内,再展开数组内的属性,如:
<h3>当前最新的count值为:{{count}}</h3>
import { mapState } from 'vuex'
computed: {
...mapState(['count']) // 用...展开运算符把Count展开在资源属性里,用上了辅助函数的时候,获取state里面的数据就不用$store.state.count了,直接count
}
如果是mutation的话,可以把辅助函数写在方法里面,展开数组里的方法体,调用store里面的mutaion的方法体和传递参数;如:
<template>
<div>
<h3>当前最新的count值为:{{count}}</h3>
<button @click="handleDel">-1</button>
<button @click="DelN">-N</button>
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
export default {
name: 'subtraction',
components: {},
data () {
return {
}
},
// 用另一种方法提交变更的数据
// 通过辅助函数来实现提交,记得传递参数
methods:{
...mapMutations(['del','jian']),
handleDel(){
this.del(1)
},
DelN(){
this.jian(3)
}
},
computed: {
...mapState(['count']) // 用...展开运算符把Count展开在资源属性里,用上了辅助函数的时候,获取state里面的数据就不用$store.state.count了,直接count
}
}
</script>
<style scoped>
</style>
这次先写到这里,里面的单词在总结的时候经常有写错,请多包涵,看到错误的请指正,谢谢。