「网页开发|前端开发|Vue」09 Vue状态管理Vuex:让页面根据用户登录状态渲染不同内容

本文主要介绍如何通过Vue的状态管理框架Vuex来管理一些被不同组件或不同页面共同使用的数据,然后展示如何通过状态管理用户信息,并且在具体页面获取用户信息,并且根据用户信息的不同展示不同的页面内容。

本系列前文传送门


一、场景说明

我们在网站开发中,有些数据可能会被不同的组件或者在不同页面多次使用,对于这种重复多次使用的数据,如果每次都要重新获取或者重新生成,那么除了代码会变得冗余,还可能因为代码改动过程中的遗漏导致不同地方数据不一致而引发数据问题。

针对这种数据在多次使用的场景,我们会使用状态管理框架来统一管理数据,使得程序更加稳定和可预测。

react的状态管理使用redux,而vue的状态管理使用vuex。接下来我们就介绍一下vuex的核心内容,然后用一个根据用户登录状态数据展示不同页面内容的例子来展示状态管理的具体应用场景和实现方法。

二、状态管理Vuex

如果用编程语言中我们熟悉的概念来描述状态管理的话,那状态管理就相当于一个「全局变量」,我们可以在项目的各个位置直接获取、使用、甚至更新变量的内容。

安装vuex

因为我们在示例中用的是匹配vue2vuex3,所以安装时需要注意版本,如下:
npm install vuex@3

状态管理 - 创建状态

因为状态管理是管理着涉及整个项目的状态数据,所以一般我们会新建一个store目录,在该目录下组织状态相关的代码。这里我们为了更快更简单地展示创建状态的过程,则直接在src/main.js添加代码,如下:
在这里插入图片描述

状态管理 - 在代码各处使用创建的状态

创建状态管理store,并且传入到Vue实例中后,我们就可以在项目的各个代码中访问store中的状态数据了。

如果我们是在src/main.js中访问,直接使用变量名store即可(因为我们就是在这里将状态管理实例导入为store),比如console.log(store.state.count)

如果是在其他文件中,比如在HelloWorld.vue中,则使用this.$store来访问,比如console.log(this.$store.state.count)

状态管理 - 在代码中更新状态管理的值

我们可以像修改变量值一样,直接修改状态的值。这给了我们极大的自由,但是这也可能会导致我们管理的状态被以各种方式被修改,导致出现预期之外的结果。

所以会推荐开启严格模式(在创建store时传入strict: true),然后封装修改对应状态值的方法供代码各处调用。相当于回归了程序员的本质:降低系统复杂度、降低程序不确定性。

那么vuex的设计中,如何封装方法并在代码各处调用的呢?
那就是在创建store时,定义mutationsactions两个字段,并在字段值中定义各个方法。两个字段都可以定义操作状态值的方法,主要差别是:

  • mutations是同步操作,actions是异步操作;
  • mutations直接操作状态值,actions使用commit(方法名)调用mutations方法操作状态值

所以我们可以将创建的store改为如下:

const store = new Vuex.Store({
  strict: true,
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    asyncIncrement (context) {
      context.commit('increment')
    }
  }
})

然后就可以在项目的各处代码中使用this.$store.commit(mutations中的方法名)以及this.$store.dispatch(actions中的方法名)来调用mutationsactions中定义的方法。

比如我们在HelloWorld.vuescript中增加如下方法:

    methods: {
        increase() {
            console.log(`[ Before ] ${this.$store.state.count}`);
            this.$store.commit("increment");
            console.log(`[ After ] ${this.$store.state.count}`);
        },
        asyncIncrease() {
            console.log(`[ Before ] ${this.$store.state.count}`);
            this.$store.dispatch("asyncIncrement");
            console.log(`[ After ] ${this.$store.state.count}`);
        },
    },

然后在template的部分增加count的展示以及两个更新count的按钮,如下:
在这里插入图片描述
返回页面,我们就可以看到浏览器页面已经展示count的值以及两个增加按钮,如下:
在这里插入图片描述
我们可以点按两个按钮来观察同步和异步的效果,如下:
在这里插入图片描述
我们可以看到我们点击异步的时候,由于我们在代码中设置了等待1秒再增加count的值,所以输出的前后值是相同的,等待1s后再点击按钮就可以观察到值已经变化。最后我们连续快速点击3次异步增加,可以看到3次点击完成后,值仍然是4,但是等待1秒之后,值变成了7(看页面按钮上面展示的count值)

三、用户登录数据如何流转如何变化

在明白状态管理的基本操作之后,我们就可以来考虑一个状态管理的常见场景:管理用户登录信息。

首先,我们要确认要放到状态管理中的信息是不是会在多个地方使用到。用户登录信息是用户登录之后,在网站的各个页面都应该是共用的,最起码右上角显示的用户登录状态都应该是一致的,不能首页登录后右上角已经显示了用户登录状态,切换到其他页面右上角又变成了登录/注册按钮。所以用户登录信息确实适合放到状态管理中。

然后我们考虑用户登录信息的存储结构。比如我们可以放一个名为userobject值在store.state中,然后在各个页面通过访问this.$store.state.user.具体用户信息字段访问用户信息中的各个信息。

于是我们就可以清楚用户注册/登录的一个基本流程了,如下:

  • 我们在页面检查状态管理store中是否存在user,需要不存在用户信息,则在页面右上角显示"登录/注册"按钮;
  • 当我们通过注册/登录页面进行注册和登录后,在状态管理中存入对应的用户信息(用户来自后端,所以涉及接口交互);
  • 状态管理中的用户信息变化后,页面检测到store中的user已经存在,自动重新渲染,在页面右上角渲染出登录的用户信息。

四、简单模拟用户登录过程

明白用户登录的基本流程之后,我们可以简单通过代码模拟一下整个过程。实际的登录过程涉及接口请求以及登录和注册页的开发,我们目前只是要模拟登录前后的页面变化,所以将流程简化如下:

  • 页面检查store中是否有用户信息,如果没有,展示一个登录按钮 ;否则展示用户信息以及一个登出按钮;
  • 登录按钮增加功能:点击后往store中写入用户信息;
  • 登出按钮增加功能:点击后删除store中的用户信息;
  • 通过点击登录登出来观察用户信息变化与页面变化过程;

首先在src/main.js中增加代码,用来创建store,在store中定义登录和注销登录的方法,如下:

const store = new Vuex.Store({
    state: {
        user: {}
    },
    mutations: {
        mock_login() {
            this.state.user = {
                userId: 1111,
                userName: "明仔的阳光午后",
            };
            sessionStorage.setItem("user", JSON.stringify(this.state.user));
        },
        mock_logout() {
            this.state.user = undefined;
            sessionStorage.removeItem("user");
        },
    },
})

然后在HelloWorld.vuescript的部分添加从store中获取user信息以及操作user信息的方法,如下:

<script>
export default {
    data() {
        return {
            user: JSON.parse(sessionStorage.getItem("user")),
        };
    },
    methods: {
        login() {
            this.$store.commit("mock_login");
            this.user = this.$store.state.user;
        },
        logout() {
            this.$store.commit("mock_logout");
            this.user = this.$store.state.user;
        },
    },
}
</script>

之后在HelloWorld.vuetemplate部分增加一个h1用来展示当前登录状态,一个button用来提供登录和登出的点按功能,这样我们才能直接通过点按来模拟登录过程并观察页面内容变化。如下:

<template>
    <div id="app">
        <div v-if="user">
            <h1>Hi, {{ user.userName }}</h1>
            <button @click="logout">登出</button>
        </div>
        <div v-else>
            <h1>当前未登录</h1>
            <button @click="login">登录</button>
        </div>
    </div>
</template>

完成上述代码改动,我们就可以回到浏览器页面,看到页面内容如下:
在这里插入图片描述
我们点击登录按钮之后,页面变化如下:
在这里插入图片描述

我们看到,页面的标题展示了具体的用户名,同时登录按钮变成了登出按钮。可以验证页面实现了根据用户登录状态来渲染不同的内容。

所以通过这样一个过程,我们就可以在其他需要页面根据不同数据,比如用户登录状态,或者用户身份、用户权限等等,来渲染不同页面内容的应用场景中,按照上述的流程来轻松实现我们想要的需求。

比如可以自己试试让导航栏根据用户登录状态来展示用户信息或者登录/注册按钮。


写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~👇

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明仔的阳光午后

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值