(二)vue store状态管理模式
一、介绍:1、状态管理(vuex)简介:vuex是专为vue.js应用程序开发的状态管理模式。它采用集中存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。vuex也集成刀vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。2、Vuex 的思想:当我们在页面上点击一个按钮,它...
一、介绍:
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默认存储方式存储,可以这样:
更多推荐
所有评论(0)