该文章能帮助你在 Vue 项目中存储用户信息;理解 Vuex 的使用场景;降低组件间的耦合度。
随着软件产品的规模越来越庞大,维护难题犹如洪水般便向工程师涌来。前端工程师不仅要将设计稿中的元素组件化,便于组合使用;同时要关注各种逻辑代码间的耦合,避免产生过多的重复片段。
前端经常遇到两个页面共用一个状态,如显示用户的昵称;判断是否登录,显示“登录”按钮等。在简单的应用中,我们可以编写一个维护状态的模块,在适当的时候读取或者更新状态。
使用 User State 模块管理两个页面中的状态
但状态模块难以应付在大型应用中复杂的场景。还需引入发布订阅的设计,让页面无需时刻关注状态更新;一旦多处使用,很难追踪到底是哪里更新了状态。
为什么是 Vuex?
避免出现状态模块那样的缺陷,Vuex 有两个特点:
- 像 Vue 响应式数据那样,状态以响应式结果反馈至组件、页面;
- 为保证状态的变化是可追踪的,只允许以一种方式改变状态;
通过阅读状态管理模式, Vuex 中存在几个核心概念:
- State 意为状态源,以对象结构储存的值
- Getter 可以从 State 中派生出一些状态,方便具体情况使用
- Mutation 是唯一可以改变 State 的方法,且必须是同步函数调用
- Action 可以异步地提交 Mutation
通过理解以上概念,梳理出与用户相关的功能。例如:
- 用户昵称、认证信息等储存在 State 中;
- 将异步获取用户信息的操作编写在 Action 函数;
- 把具体更新昵称、认证信息等操作编写在 Mutation 函数;
- Getter 则返回用来快速判断用户是否登录的判断;
应用场景
回到最初要显示用户昵称,判断是否登录的场景。意味着 Vuex 必须暴露两个 Getter ,isLogin
和 account
提供外部使用。
// store/account.js
export const IS_LOGIN = 'account/isLogin'
export const ACCOUNT = 'account/account'
export const getters = {
isLogin() {},
account() {}
}
isLogin
为布尔值,表示是否登录。account
对象含有用户的信息,包括昵称、会员等级等。
导出到计算属性
为了能在组件中快速读取用户的信息,使用 Vuex 提供的 mapGetters
将两个 Getter isLogin
和 account
生成为计算属性,并抽象成混入 (mixins)。
// packages/mixins/Auth.mixin.js
import { mapGetters } from "vuex"
import { IS_LOGIN, ACCOUNT } from "@/store/account"
export default function () {
return {
computed: {
...mapGetters({
'isLogin': IS_LOGIN,
'account': ACCOUNT
})
}
}
}
// Vue Component
import AuthMixin from "./Auth.mixin"
export default function() {
return {
mixins: [AuthMixin()],
beforeMount () {
console.log(this.isLogin)
console.log(this.account)
}
}
}
将 Auth.mixin
混入到组件,随时随地能读取到 isLogin
account
。接下来开始完善 Vuex 的内部状态源 State 。
状态源
export const state = () => ({
user: null,
token: "",
})
更新状态
export const mutations = {
set_user(state, user) {
state.user = user
},
set_token(state, token) {
state.token = token
},
}
export const actions = {
async getUser({ state, commit }, { user_id, token }) {
const result = await $user.find({ token, user_id })
result.id = user_id
commit('set_user', result)
commit('set_token', token)
return Promise.resolve(result)
},
}
在 Vue 框架中,Vuex 状态管理会使得简单的应用变得复杂,开发者需要权衡其带来的好处和效益。