一、介绍:

1、状态管理(vuex)简介:vuex是专为vue.js应用程序开发的状态管理模式。它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。

2、Vuex 的存储过程:

在页面上触发(dispatch)action, action 随后会执行(commit)一个mutation, mutation 会改变state, state 改变以后,再在页面上从state 获取数据。

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

二、状态管理核心状态管理有5个核心,分别是state、getter、mutation、action以及module。
1、state:属性
state为单一状态树,在state中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在vue.js的组件中才能获取你定义的这个对象的状态。
2、getter:类似于get方法,get属性
getter有点类似vue.js的计算属性,当需要从store的state中派生出一些状态,就可以使用getter,getter会接收state作为第一个参数,而且getter的返回值会根据它的依赖被缓存起来,只有getter中的依赖值(state中的某个需要派生状态的值)发生改变的时候才会被重新计算。
3、mutation:类似于set方法,给state属性复制
更改store中state状态的唯一方法就是提交mutation,就很类似事件。每个mutation都有一个字符串类型的事件类型和一个回调函数,改变state的值就要在回调函数中改变。调用方法:store.commit(set方法名,args......)。
4、action:逻辑函数,调用方法:store.dispatch(action方法名,args......)
在action中可以执行store.commit提交mutation,也可以使用store.dispatch调用其他action方法,而且action中可以有任何的异步操作。

5、module :其实只是解决了当state中很复杂臃肿的时候,module可以将store分割成模块,每个模块中拥有自己的state、mutation、action和getter。

简单的 store 模式

var store = {
  debug: true,
  state: {
    message: 'Hello!'
  },
  setMessageAction (newValue) {
    if (this.debug) console.log('setMessageAction triggered with', newValue)
    this.state.message = newValue
  },
  clearMessageAction () {
    if (this.debug) console.log('clearMessageAction triggered')
    this.state.message = ''
  }
}

所有 store 中 state 的改变,都放置在 store 自身的 action 中去管理。这种集中式状态管理能够被更容易地理解哪种类型的 mutation 将会发生,以及它们是如何被触发。当错误出现时,我们现在也会有一个 log 记录 bug 之前发生了什么。

此外,每个实例/组件仍然可以拥有和管理自己的私有状态:

var vmA = new Vue({
  data: {
    privateState: {},
    sharedState: store.state
  }
})

var vmB = new Vue({
  data: {
    privateState: {},
    sharedState: store.state
  }
})

三、具体应用步骤实例:

1、定义store:index.js是入口,实例化store 的,但是存储的东西比较多全部写在index.js里面不太容易维护,可以拆分成多个文件(如这里拆分成getters.js和modules里面的几个文件),然后在index.js里面引入进来

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import permission from './modules/permission'
import user from './modules/user'
import getters from './getters'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    permission,
    user
  },
  getters
})

export default store

2、定义store中的属性:如这里用name来保存用户名:

(1)先在user.js的state中定义属性,并在mutations中定义set方法用于后面给属性赋值

 state: {
    token: getToken(),
    name: '',
    authorities: [],
    roles: [],
    navbars:[]
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, name) => {
      state.name = name
    },
    SET_PERMISSION: (state, authorities) => {
      state.authorities = authorities
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_NAVBARS: (state, navbars) => {
      state.navbars = navbars
    }
  },

(2)再在getters中声明,

const getters = {
  sidebar: state => state.app.sidebar,
  //token
  token: state => state.user.token,
  //用户名
  name: state => state.user.name,
  //角色
  roles: state => state.user.roles,
  //后台返回的权限code
  authorities:state =>state.user.authorities,
  //动态权限路由
  permission_routers: state => state.permission.routers,
  //固定权限路由
  addRouters: state => state.permission.addRouters
}
export default getters

3、定义函数:在user.js的actions中定义函数,如这里的GetCurrentUser是获取并存储用户名的:

actions: {
    // 登录
    Login({ commit }, user) {
      const userName = user.userName
      const pwd = user.password
      return new Promise((resolve, reject) => {
        login(user).then(response => {
          const data = response.data
          setToken(data)
          commit('SET_TOKEN', data)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    //获取登录用户
    GetCurrentUser({ commit }) {
      return new Promise((resolve, reject) => {
        getCurrentUser().then(response => {
          const data = response.data
          commit('SET_NAME', data.userName)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 获取用户权限信息
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getMyAuthorities().then(response => {
          console.info('res' + response)
          const data = response.data
          var permissions = []
          data.forEach(item=>{
            permissions.push(item.authorityCode);
          })
          
          commit('SET_PERMISSION', permissions)

          resolve(permissions)
        }).catch(error => {
          reject(error)
        })
      })
    },


    // 登出
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_PERMISSION', [])
          removeToken()
          logout().then(response=>{})
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 前端 登出
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        removeToken()
        resolve()
      })
    }
  }

4、引用store:

(1)方法一: this.$store;

(2)方法二:先使用import store from './store'引入store,之后直接使用store操作。

5、调用store中的actions(方法):dispatch(functionName,args......),第一个参数为函数名,后面参数为入参

  如,登录页面调用Login,在Login方法中存储一些全局变量:

 methods: {
  
    login() {
      this.user.password = getDAes(this.user.password),
      this.$store.dispatch("Login", this.user).then(() => {
        this.$router.push({ path: "/" });
      });
    }
  }

  再如: 

import store from '../../store/index'
 store.dispatch('updateNode', {
        action: 'add'
      })
.......

 UPDATE_NODE: (state, params) => {
      if (params.action === 'add') { // 新增事件
         //新增逻辑
      } else if (params.action === 'delete') { // 删除事件
        //删除逻辑
    }

.......

updateNode({ commit }, params) {
      commit('UPDATE_NODE', params)
    },

.......

  6、调用store中的 state(属性):

(1)方法一:从store.getters中获取:

   如:

import store from './store'

router.addRoutes(store.getters.addRouters)// 添加动态路由

(2)方法二:从mapGetters中获取,使用import { mapGetters } from 'vuex'引用mapGetters,之后在computed中获取值,这样直接使用this.属性名称就可以调用了(同data中数据使用方法一样)。如:

<template>
  <div class="dashboard-container">
    <div class="dashboard-text">欢迎:{{name}}</div>
    <div class="dashboard-text">您当前角色为:<span v-for='role in roles' :key='role'>{{role}}</span></div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  name: 'dashboard',
  computed: {
    ...mapGetters([
      'name',
      'roles'
    ])
  }
}
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.dashboard {
  &-container {
    margin: 30px;
  }
  &-text {
    font-size: 30px;
    line-height: 46px;
  }
}
</style>

(3)方法三:从state中获取:如

computed: {
    sidebar() {
      return this.$store.state.app.sidebar
    },
    device() {
      return this.$store.state.app.device
    }
}

***********************************************************************************************************************************************

总的代码为:

inde.js:

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import permission from './modules/permission'
import user from './modules/user'
import getters from './getters'
import VuexPersistence from 'vuex-persist';

Vue.use(Vuex)

const vuexLocal = new VuexPersistence({
  storage: window.localStorage
})

const store = new Vuex.Store({
  modules: {
    app,
    permission,
    user
  },
  getters,
  plugins: [vuexLocal.plugin]
})

export default store

 getters.js:

const getters = {
  sidebar: state => state.app.sidebar,
  //token
  token: state => state.user.token,
  //用户名
  name: state => state.user.name,
  //角色
  roles: state => state.user.roles,
  navbars: state => state.user.navbars,
  //后台返回的权限code
  authorities:state =>state.user.authorities,
  //动态权限路由
  permission_routers: state => state.permission.routers,
  //固定权限路由
  addRouters: state => state.permission.addRouters
}
export default getters

user.js:

import { login, logout, getMyAuthorities , getNavMenu } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { getCurrentUser } from '@/api/user'

const user = {
  state: {
    token: getToken(),
    name: '',
    authorities: [],
    roles: [],
    navbars:[]
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, name) => {
      state.name = name
    },
    SET_PERMISSION: (state, authorities) => {
      state.authorities = authorities
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_NAVBARS: (state, navbars) => {
      state.navbars = navbars
    }
  },

  actions: {
    // 登录
    Login({ commit }, user) {
      const userName = user.userName
      const pwd = user.password
      return new Promise((resolve, reject) => {
        login(user).then(response => {
          const data = response.data
          setToken(data)
          commit('SET_TOKEN', data)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    //获取登录用户信息
    GetCurrentUser({ commit }) {
     
      return new Promise((resolve, reject) => {
        getCurrentUser().then(response => {
          const data = response.data
          commit('SET_NAME', data.userName)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    //获取登录用户navbars
    GetNavBars({ commit }) {
      return new Promise((resolve, reject) => {
        getNavMenu().then(response => {
          const data = response.data
          commit('SET_NAVBARS', data)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 获取用户权限信息
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getMyAuthorities().then(response => {
          console.info('res' + response)
          const data = response.data
          var permissions = []
          data.forEach(item=>{
            permissions.push(item.authorityCode);
          })
          
          commit('SET_PERMISSION', permissions)

          resolve(permissions)
        }).catch(error => {
          reject(error)
        })
      })
    },


    // 登出
    LogOut({ commit, state }) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('SET_TOKEN', '')
          commit('SET_PERMISSION', [])
          removeToken()
          logout().then(response=>{})
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },

    // 前端 登出
    FedLogOut({ commit }) {
      return new Promise(resolve => {
        commit('SET_TOKEN', '')
        removeToken()
        resolve()
      })
    }
  }
}

export default user

 permission.js:

import { asyncRouterMap, constantRouterMap } from '@/router/index'

/**
 * 通过meta.authority判断是否与当前用户权限匹配
 * @param authorities
 * @param route
 */
function hasPermission(authorities, route) {
  if (route.meta && route.meta.authority) {
    return authorities.some(authority => route.meta.authority.indexOf(authority) >= 0)
  } else {
    return true
  }
}

/**
 * 递归过滤异步路由表,返回符合用户角色权限的路由表
 * @param asyncRouterMap
 * @param authorities
 */
function filterAsyncRouter(asyncRouterMap, authorities) {
  const accessedRouters = asyncRouterMap.filter(route => {
    if (hasPermission(authorities, route)) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, authorities)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes({ commit }, data) {
      return new Promise(resolve => {
        const { authorities } = data
        let accessedRouters
        if (authorities.indexOf('admin') >= 0) {
          accessedRouters = asyncRouterMap
        } else {
          accessedRouters = filterAsyncRouter(asyncRouterMap, authorities)
        }
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

export default permission

app.js:

import Cookies from 'js-cookie'

const app = {
  state: {
    sidebar: {
      opened: !+Cookies.get('sidebarStatus'),
      withoutAnimation: false
    },
    device: 'desktop'
  },
  mutations: {
    TOGGLE_SIDEBAR: state => {
      if (state.sidebar.opened) {
        Cookies.set('sidebarStatus', 1)
      } else {
        Cookies.set('sidebarStatus', 0)
      }
      state.sidebar.opened = !state.sidebar.opened
      state.sidebar.withoutAnimation = false
    },
    CLOSE_SIDEBAR: (state, withoutAnimation) => {
      Cookies.set('sidebarStatus', 1)
      state.sidebar.opened = false
      state.sidebar.withoutAnimation = withoutAnimation
    },
    TOGGLE_DEVICE: (state, device) => {
      state.device = device
    }
  },
  actions: {
    ToggleSideBar: ({ commit }) => {
      commit('TOGGLE_SIDEBAR')
    },
    CloseSideBar({ commit }, { withoutAnimation }) {
      commit('CLOSE_SIDEBAR', withoutAnimation)
    },
    ToggleDevice({ commit }, device) {
      commit('TOGGLE_DEVICE', device)
    }
  }
}

export default app

 

四、store永久存储VuexPersistence:

store默认只在本页面且不刷新页面的情况下有效,刷新页面或者在同一个浏览器重新打开页面store中存储的内容都会被清空。上面的例子中name、roles、authorities、token这些之所以一直可以取到值,是因为在permission.js中做了判断,从store中获取不到就重新掉接口获取并再次存储到store中。

永久存储可以使用localStorage或者sessionStorage,即比如登录的时候调用后端接口,在store的set方法中存储到Storage中,后面的get方法从Storage中取值,这时的store只是一个框架,主要还是localStorage(sessionStorage)。除此之外,store也自带永久存储VuexPersistence

1、永久存储:VuexPersistence可以永久存储,刷新页面或者重新打开页面store中的值还在。

(1)npm install --save vuex-persist

(2)在定义vuex的地方加上:

Vue.use(Vuex)

const vuexLocal = new VuexPersistence({
  storage: window.localStorage
})

const store = new Vuex.Store({
  ...自定义的其他内容...
  plugins: [vuexLocal.plugin]
})

export default store

如我的:

import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import permission from './modules/permission'
import user from './modules/user'
import getters from './getters'
import VuexPersistence from 'vuex-persist';

Vue.use(Vuex)

const vuexLocal = new VuexPersistence({
  storage: window.localStorage
})

const store = new Vuex.Store({
  modules: {
    app,
    permission,
    user
  },
  getters,
  plugins: [vuexLocal.plugin]
})

export default store

2、指定值永久存储:如果只希望指定值永久存储,其他值按照vuex store默认存储方式存储,可以这样:

Logo

前往低代码交流专区

更多推荐