在上一篇 【Vue框架】Vue路由配置 结尾时说到store.js,在代码里new Vuex.Store()
传入了getters对象;本篇专门针对getters的内容进行整理。
// 用于存储获取状态的方法
const getters = {
// 这里的state参数,是store\index.js的modules
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,
name: state => state.user.name,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permission_routes: state => state.permission.routes,
errorLogs: state => state.errorLog.logs
}
export default getters
对于后端菜鸟&前端小白的我来说,单看getter.js的代码只感觉到一脸懵逼,然后留下两个问题。
这个state从哪来的(在哪引入的)?state里面的东西是什么时候定义的?
回顾一下 【Vue框架】Vue路由的配置 中的store.js,在store.js中变量modules
获取了@/store/modules/*.js
,然后注册到Vuex的实例store
中,并以getters.js的getters
来对这些存储的状态进行管理。
答:在store.js中引入,Vuex管理的;在modules文件夹下的js文件中定义的。
【这个回答多少有点简单,下面具体一点,用一个例子来稍微深入说明】
getters
函数中的 state
是一个参数,用于接收并访问Vuex的状态。state.app.sidebar
中,state
实际上是指向Vuex的store
对象中的state
,而不是modules/app.js
模块中的state
。modules
对象作为选项传递给 new Vuex.Store
构造函数,将各个子模块的状态添加到Vuex的总状态树中。这样,每个模块的状态就会成为Vuex的根状态树的一个子属性。getters
函数中,我们可以通过 state
参数来访问这个总状态树中的各个子模块的状态。因此,当 state.app.sidebar
位于 getters
函数中时,它实际上是访问了modules/app.js
模块中的 state
对象的 sidebar
属性。总结来说,getters
函数中的 state
参数用于获取Vuex中的状态,在多模块的情况下,它可以访问根状态树中各个子模块的状态,包括 state.app.sidebar
,这是因为在创建Vuex实例时将各个子模块的状态添加到了根状态树中。
// 从 'js-cookie' 模块中导入 Cookies 对象,用于在浏览器中操作和管理 cookie
import Cookies from 'js-cookie'
// 定义`state`变量,为了与Vuex中,`getters` 函数中的 `state`对应,这里是获取前端页面状态(用户看到的,不是指前端代码)
const state = {
// 定义的 `sidebar` 对象包含了应用左侧菜单栏的状态
sidebar: {
// 一个布尔值,表示左侧菜单栏是否打开。
// 它首先检查 `Cookies` 中是否存在名为 `sidebarStatus` 的 cookie,如果存在则将其转换为布尔值,否则默认为 `true`
// !!+会把字符串的 “0” 转成 false,或者把 字符串的 “1” 转成 true
opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
// 一个布尔值,用于指示是否要在打开或关闭左侧菜单栏时应用动画效果
withoutAnimation: false
},
// 定义了一个名为 `device` 的属性,并将其初始化为字符串 `'desktop'`,表示应用的设备类型,默认为桌面设备
device: 'desktop',
// 此属性用于定义应用的基本大小,例如元素的字体大小、组件的尺寸等
size: Cookies.get('size') || 'medium'
}
// 用于存储一系列 改变 应用状态的方法
const mutations = {
// 用于切换左侧菜单栏的状态
TOGGLE_SIDEBAR: state => {
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
},
// 用于关闭左侧菜单栏
CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 0)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
// 用于切换设备类型
TOGGLE_DEVICE: (state, device) => {
state.device = device
},
// 用于设置应用的基本大小
SET_SIZE: (state, size) => {
state.size = size
Cookies.set('size', size)
}
}
// 用于存储一系列 触发改变 应用状态的方法
// 用于处理异步操作或复杂逻辑
const actions = {
// 用于触发切换左侧菜单栏状态的行为
// 解构赋值参数 `{ commit }`,从 `context` 对象中提取 `commit` 方法,`commit` 用于触发对应的 `mutations` 方法
toggleSideBar({ commit }) {
// commit() 里面的字符串 是要触发具体 `mutations` 方法的名称
commit('TOGGLE_SIDEBAR')
},
closeSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
toggleDevice({ commit }, device) {
// commit() 的第二个参数是可选参数,它是传递给 `mutations` 方法的数据载荷,用于更新状态
commit('TOGGLE_DEVICE', device)
},
setSize({ commit }, size) {
commit('SET_SIZE', size)
}
}
// 默认导出一个对象,包含了模块的相关配置
export default {
// 设置模块的命名空间为 `true`,这意味着该模块中的状态、mutations、getters、actions将被封装在命名空间中,以避免和其他模块的冲突
namespaced: true,
// 模块的状态
state,
// 模块的变化方法
mutations,
// 模块的行为方法
actions
}
简单说,就是等号左右两边格式对应上。
面对{ }
这种的就是前端的对象,它的属性没有次序,变量必须与属性同名,才能取到正确的值。
参考: 解构赋值详解(详细解释易懂)
在上面的代码中,提到 解构赋值参数 { commit }
是从 context
对象中提取出来的,这个 context
对象是什么?
在 Vuex 中,
context
对象是一个由 Vuex 提供的包含了一些方法和属性的上下文对象。它是在每个 Vuex 模块的 action、mutation、getter 和 module 方法中作为一个参数传入的。
具体来说,
context
对象中包含了以下属性和方法:
context.state
:当前模块的 state 对象。context.getters
:当前模块的 getters 对象。context.commit
:用于触发 mutation 的方法。context.dispatch
:用于触发 action 的方法。context.rootState
:根模块的 state 对象(如果有嵌套模块)。context.rootGetters
:根模块的 getters 对象(如果有嵌套模块)。
这些属性和方法可以在 Vuex 模块中进行状态管理和相应的操作。
eg.在一个模块的 action 中使用 context
对象:
const moduleA = {
state: { /* ... */ },
getters: { /* ... */ },
mutations: { /* ... */ },
actions: {
myAction(context) {
console.log(context.state); // 当前模块的 state 对象
console.log(context.getters); // 当前模块的 getters 对象
context.commit('mutationA'); // 触发当前模块的 mutation 方法
context.dispatch('myActionB'); // 触发当前模块的另一个 action 方法
console.log(context.rootState); // 根模块的 state 对象(如果有嵌套模块)
console.log(context.rootGetters); // 根模块的 getters 对象(如果有嵌套模块)
},
myActionB(context) {
// ...
},
},
};
在上述代码中,context
参数是在 myAction
方法中传递的。通过使用 context
对象,我们可以访问当前模块的状态(state
)和计算属性(getters
)、触发当前模块的变更(commit
和 dispatch
),以及根模块的状态和计算属性。
context
对象是 Vuex 提供给开发者在模块中进行状态管理的重要工具之一。它提供了一些方法和属性来操作和访问模块中的状态,以实现响应式的状态管理。