该文章能帮助你在 Vue 项目中存储用户信息;理解 Vuex 的使用场景;降低组件间的耦合度。

随着软件产品的规模越来越庞大,维护难题犹如洪水般便向工程师涌来。前端工程师不仅要将设计稿中的元素组件化,便于组合使用;同时要关注各种逻辑代码间的耦合,避免产生过多的重复片段。

前端经常遇到两个页面共用一个状态,如显示用户的昵称;判断是否登录,显示“登录”按钮等。在简单的应用中,我们可以编写一个维护状态的模块,在适当的时候读取或者更新状态。

使用 User State 模块管理两个页面中的状态

但状态模块难以应付在大型应用中复杂的场景。还需引入发布订阅的设计,让页面无需时刻关注状态更新;一旦多处使用,很难追踪到底是哪里更新了状态。

为什么是 Vuex?

避免出现状态模块那样的缺陷,Vuex 有两个特点:

  • 像 Vue 响应式数据那样,状态以响应式结果反馈至组件、页面;
  • 为保证状态的变化是可追踪的,只允许以一种方式改变状态;

通过阅读状态管理模式, Vuex 中存在几个核心概念:

  • State 意为状态源,以对象结构储存的值
  • Getter 可以从 State 中派生出一些状态,方便具体情况使用
  • Mutation 是唯一可以改变 State 的方法,且必须是同步函数调用
  • Action 可以异步地提交 Mutation

通过理解以上概念,梳理出与用户相关的功能。例如:

  • 用户昵称、认证信息等储存在 State 中;
  • 将异步获取用户信息的操作编写在 Action 函数;
  • 把具体更新昵称、认证信息等操作编写在 Mutation 函数;
  • Getter 则返回用来快速判断用户是否登录的判断;

应用场景

回到最初要显示用户昵称,判断是否登录的场景。意味着 Vuex 必须暴露两个 Getter ,isLoginaccount 提供外部使用。

// store/account.js

export const IS_LOGIN = 'account/isLogin'
export const ACCOUNT = 'account/account'

export const getters = {
    isLogin() {},
    account() {}
}

isLogin 为布尔值,表示是否登录。
account 对象含有用户的信息,包括昵称、会员等级等。

导出到计算属性

为了能在组件中快速读取用户的信息,使用 Vuex 提供的 mapGetters 将两个 Getter isLoginaccount 生成为计算属性,并抽象成混入 (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 状态管理会使得简单的应用变得复杂,开发者需要权衡其带来的好处和效益。

参考

标签: none

添加新评论