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.passwordreturn 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' // pluginsimport './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 = falsenew Vue({el: '#app',router,store,render: h => h(App)
})