Vue 2.0 中的 Vuex Store 状态管理器核心概念和组成部分
- State(状态):
Vuex Store 的核心就是集中式存储应用的所有组件的状态。它是一个单一状态树,所有的组件都从这个状态树中读取数据并可以响应状态的变化。
const state = {
count: 0,
user: null,
// 更多的状态...
}
- Getters(获取器):
类似于 Vue 组件中的计算属性,Getters 接受 State 作为输入,并返回处理过的状态数据。它们允许你定义从 State 派生出的新状态,且当 State 改变时自动更新。
const getters = {
formattedCount: state => `Count is ${state.count}`,
loggedInUser: state => state.user && state.user.loggedIn ? state.user : null,
// 更多的获取器...
}
- Mutations(突变)
修改 Vuex Store 中的状态的唯一方式是通过提交 mutation。每个 mutation 都是一个纯函数,接受 State 作为第一个参数,并接收 payload 作为额外参数来修改 State。
const mutations = {
increment(state) {
state.count++;
},
setUser(state, user) {
state.user = user;
},
// 更多的突变...
}
- Actions(动作)
Actions 是用于触发 mutations 并包含异步操作的地方。它们通常用来执行异步逻辑(如 AJAX 请求),并在完成后提交 mutation 来改变 State。某些情况下,可能需要通过异步操作来设置某个store状态,这时可以创建一个action来处理整个过程,并在成功后调用mutation更新状态。
const actions = {
async incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
},
fetchUser({ commit }) {
return axios.get('/api/user')
.then(response => {
commit('setUser', response.data);
});
},
// 更多的动作...
}
- Modules(模块)
在大型应用中,Store 可以被细分为多个模块,每个模块拥有自己的 State、Getters、Mutations 和 Actions。这样有助于组织代码,使得状态管理更加清晰和可维护。
// example module
const userModule = {
state: { ... },
getters: { ... },
mutations: { ... },
actions: { ... },
}
export default new Vuex.Store({
modules: {
user: userModule,
// 其他模块...
}
})
- 完整应用示例
文件结构:
store/modules/…:被细分的模块
store/index.js:总和被细分的模块
store/getters.js:接受 State 作为输入,并返回处理过的状态数据, State 改变时自动更新。
main.js:引入store并应用到vue
以细分模块user.js为例:
(1)user.js
import { login, logout } from '@/api/login' /* 自己封装的登录退出请求*/
import { getToken, setToken, removeToken } from '@/utils/auth' /*cookie管理token文件*/
const user = {
state: {
token: getToken(),
userName: localStorage.getItem("userName")||'',//用户名
permissions: [],
isRouter:true,
isLargeScreen:JSON.parse(localStorage.getItem("isLargeScreen")||"true"),//全屏显示驾驶舱
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
USER_NAME: (state, userName) => {
state.userName = userName
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
},
IS_ROUTER: (state, isRouter) => {
state.isRouter = isRouter
},
IS_LargeScreen(state, isLargeScreen){
state.isLargeScreen = isLargeScreen
},
changeStateMutations1(state, data) {
//data:{key:需要修改的名,data:修改的内容}
state[data.key] = data.data;
if (typeof(state[data.key]) != "undefined") {
return true;
} else {
return false;
}
},
system_ID:(state, systemId)=>{
state.systemId = systemId
},
IS_System:(state, isSystem)=>{
state.isSystem = isSystem
}
},
actions: {
setSuperAdminType({ commit, state }, view) {
return new Promise(resolve => {
resolve([...state.superAdminType])
})
},
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password
return new Promise((resolve, reject) => {
login(username, password).then(res => {
//console.log(res.isAiAdmin,"登录返回值");
setToken(res.content.token)
commit('SET_TOKEN', res.content.token)
//用户名
localStorage.setItem("userName",res.content.userName)
commit('USER_NAME', res.content.userName)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 退出系统
LogOut({ commit, state }) {
return new Promise((resolve, reject) => {
logout({token:state.token}).then(() => {
commit('SET_TOKEN', '')
commit('USER_NAME', [])
removeToken()
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
removeToken()
resolve()
})
},
//修改数据
changeStateData(context, data) {
//data:{key:需要修改的名,data:修改的内容}
context.commit('changeStateMutations1', data)
},
}
}
export default user
(2)@/utils/auth(机制跟localstorage类似可以不用该文件)
import Cookies from 'js-cookie'
const TokenKey = 'Admin-cms-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}
(3)getters.js
const getters = {
sidebar: state => state.app.sidebar,
size: state => state.app.size,
device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
userName: state => state.user.userName,
introduction: state => state.user.introduction,
permissions: state => state.user.permissions,
permission_routes: state => state.permission.routes,
topbarRouters:state => state.permission.topbarRouters,
defaultRoutes:state => state.permission.defaultRoutes,
sidebarRouters:state => state.permission.sidebarRouters,
isRouter: state => state.user.isRouter,
isLargeScreen:state => state.user.isLargeScreen,
}
export default getters
(4)index.js
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
import tagsView from './modules/tagsView'
import permission from './modules/permission'
import settings from './modules/settings'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
user,
tagsView,
permission,
settings
},
getters
})
export default store
(5)main.js中引入store并运用到vue上
import Vue from 'vue'
import Cookies from 'js-cookie'
import Element from 'element-ui'
import './assets/styles/element-variables.scss'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
import './assets/icons'
import Common from "@/utils/common.js";
import App from './App'
import store from './store'
import router from './router'
import directive from './directive' // directive
import plugins from './plugins' // plugins
import './permission' // permission control
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi";
// 分页组件
import Pagination from "@/components/Pagination";
//右上角菜单
import TopMenu from "@/components/topMenu";
// 自定义表格工具组件
import RightToolbar from "@/components/RightToolbar"
// 分页组件
import newInput from "@/components/newInput";
// 头部标签组件
import VueMeta from 'vue-meta'
// 全局方法挂载
Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange
Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.handleTree = handleTree
// 全局组件挂载
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)
Vue.component('newInput', newInput)
Vue.component('TopMenu', TopMenu)
Vue.use(directive)
Vue.use(plugins)
Vue.use(VueMeta)
Vue.use(Common)
Vue.use(Element, {
size: Cookies.get('size') || 'medium' // set element-ui default size
})
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})