vue3项目实战-第六章-登录页(表单校验/模板适配/Pinia管理用户数据/持久化存储)

本文介绍了如何在Vue应用中构建登录页面,包括静态模板引入、一级路由配置、表单校验(含基础校验和自定义校验)、登录接口封装、Pinia管理用户数据以及登录状态的模板适配和请求拦截。还涉及了退出登录的逻辑处理。
摘要由CSDN通过智能技术生成

1、页面搭建与路由配置

在这里,我们要实现的是登录页面,首先,引入静态模板

紧接着,配置路由,因为它是一级路由,直接和Layout并列即可。

{
      path: '/login',
      component: Login
    }

完成之后,浏览器输入login,我们就来到了登录页下面。

2、表单校验

在这里,我们需要考虑一些问题:服务器是怎么知道用户有没有登录的?当用户点击登录的时候,服务器怎么知道用户输入的账号和密码是匹配的?如果用户输入一些乱七八糟的字符,浏览器会给出用户相应的提示吗?给出这些提示的依据是什么?代码应该怎样来编写呢?带着这些问题呢,一起来看看接下来的步骤吧

当用户输入了正确的账号和密码后,浏览器会生成一个令牌字符串Token,它可以用来记录用户当前的登录状态,如果有,说明用户就登陆了,反之,则没有登录,但是前端只能判断token的有无,而token的有效性要交给后端去判断。

那么,我们怎样避免用户输入一些乱七八糟的字符呢?就需要使用一些规则对我们的表单进行校验。通过表单校验,可以省去一些错误的请求提交,为后端节省接口压力。接下来,会详细介绍三种校验方法‘

首先,来看看实现原理

通常情况下,表单校验由三个组件共同完成:

基础步骤如下:

(1)准备表单对象

const form = ref({
  account: '',
  password: '',
  agree: true
})

(2)准备校验规则

const rules = {
  account: [
    { required: true, message: '用户名不能为空', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '密码不能为空', trigger: 'blur' },
    { min: 6, max: 14, message: '密码长度为6-14个字符', trigger: 'blur' },
  ],
  }

(3)指定表单域的校验字段名

<el-form-item prop="account" label="账户">
                <el-input v-model="form.account" />
              </el-form-item>
              <el-form-item prop="password" label="密码">
                <el-input v-model="form.password" />
              </el-form-item>

(4)把表单对象进行双向绑定

<el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-width="60px" status-icon>

由于ElementPlus内置的表单校验配置只能完成一些基本的校验,如果想要定制一些特定的校验规则,还需要开发者自己来编写相关的逻辑,接下来,看看自定义校验吧

(1)首先,定义一个agree,将其值设为true

agree:true

(2)编写逻辑

 agree: [
    {
      validator: (rule, value, callback) => {
        console.log(value)
        // 自定义校验逻辑
        // 勾选就通过 不勾选就不通过
        if (value) {
          callback()
        } else {
          callback(new Error('请勾选隐私条款和服务条款协议'))
        }
      }
    }
  ]

(3)绑定并使用

<el-form-item prop="agree" label-width="22px">
                <el-checkbox size="large" v-model="form.agree">
                  我已同意隐私条款和服务条款
                </el-checkbox>
              </el-form-item>

最后,是表单的统一校验:当用户将表单中所有的内容完成之后,点击登录按钮的时候才会通过校验,发生页面跳转

(1)获取form实例做统一校验

const formRef = ref(null)

(2)绑定

 <el-form ref="formRef" :model="form" :rules="rules" label-position="right" label-wid

运行演示:用户一上来直接点击登录

3、基础功能实现

简单介绍一下实现过程:当用户点击i登录按钮时,需要向服务器发起请求“用户要登录了”,服务器带着这个请求执行登录操作,将用户的信息保存到本地token,如果检测到账号和密码匹配成功的话,将登录结果反馈给用户。接下来,是代码实现

(1)封装登录接口

export const loginAPI = ({ account, password }) => {
  return request({
    url: '/login',
    method: 'POST',
    data: {
      account,
      password
    }
  })
}

(2)调用接口,拿到数据(登录之前先对用户输入的内容进行校验,如果校验通过,执行登录操作,反之,提示用户异常信息。)

const doLogin = () => {
  const { account, password } = form.value
  // 调用实例方法
  formRef.value.validate(async (valid) => {
    // valid: 所有表单都通过校验  才为true
    console.log(valid)
    // 以valid做为判断条件 如果通过校验才执行登录逻辑
    if (valid) {
      // TODO LOGIN
      await userStore.getUserInfo({ account, password })
      // 1. 提示用户
      ElMessage({ type: 'success', message: '登录成功' })
      // 2. 跳转首页
      router.replace({ path: '/' })
    }
  })
}

登录成功,跳转到首页,

登录失败,提示错误信息。在本项目中,直接使用测试账号,只要正常复制粘贴,不会出现登录失败的情况。

由于不只有在登录的时候会出现这个问题,其它地方可能也会出现,所以可以把错误处理相关的逻辑封装在响应拦截器里边,

详细如下:

httpInstance.interceptors.response.use(res => res.data, e => {
  // 统一错误提示
  ElMessage({
    type: 'warning',
    message: e.response.data.message
  })
  return Promise.reject(e)
})

保存之后,如果用户输入了错误的用户名或密码,就会提示相应的内容

4、Pinia管理用户数据(持久化)

由于用户数据的特殊性,在很多组件中都有可能进行共享,共享的数据可以使用Pinia来管理,更加方便后续的使用。那么,我们如何使用pinia管理数据?可以把和数据相关的所有操作(state+action)都放到pinia中,组件只负责触发action函数。

核心代码:

(1)定义用户数据

import { defineStore } from 'pinia'
import { ref } from 'vue'
import {loginAPI} from '@/apis/user'
export const useUserStore = defineStore('user', () => {
  //定义获取用户数据的state
  const userInfo = ref({})
  //定义获取接口数据的action方法
  const getUserInfo = async ({ account, password }) => {
    const res = await loginAPI({ account, password })
    userInfo.value = res.result
  }
  //以对象方式return出去
  return  {
    userInfo,
    getUserInfo
  }
  
})

(2)在index.vue中引入调用:

1)引入

import {useUserStore} from '@/stores/user'
const userStore = useUserStore()

2)使用

await userStore.getUserInfo({account,password})

这里,由于我们保存的用户数据中有一个叫token的数据,它可以用来标记用户的登录状态,但它有自己的有效期,过一段时间会失效,而Pinia中保存的数据是基于内存的,一旦刷新就会丢失,为了保持登录状态就要做到页面刷新的时候不让用户数据丢失,在这里就需要配合持久化进行存储。

这里,用到了一个新的插件Pinia-plugin-persistedstate,运行机制:在设置state的时候会自动把数据同步给localStorage,在获取state数据的时候会优先从localStorage中取。在使用之前,需要先安装,

npm i pinia-plugin-persistedstate

安装完成之后,配置这样一个属性:

 persist: true,

5、模板适配

未登录状态下,我们看到的效果是

在登录页面,点击右上角进入网站首页,显示如下效果。

而在登录状态下,我们看到的效果是这样的

那么,我们怎样实现这种效果呢?一起来看看吧

在这里,我们可以通过简单的条件渲染来实现

登录状态下

<template v-if="userStore.userInfo.token">
          <li><a href="javascript:;"><i class=" iconfont icon-user"></i>lyp1234567</a></li>
          <li>
            <el-popconfirm @confirm="confirm" title="确认退出吗?" confirm-button-text="确认" cancel-button-text="取消">
              <template #reference>
                <a href="javascript:;">退出登录</a>
              </template>
            </el-popconfirm>
          </li>
          <li><a href="/member/order">我的订单</a></li>
          <li><a href="/member">会员中心</a></li>
        </template>

非登录状态下

 <template v-else>
          <li><a href="javascript:;" @click="$router.push('/login')">请先登录</a></li>
          <li><a href="javascript:;">帮助中心</a></li>
          <li><a href="javascript:;">关于我们</a></li>
        </template>

6、请求拦截

当用户点击登录时,首先从Pinia中获取用户数据,如果有的话,根据后端要求将其拼接到Bearer后面

httpInstance.interceptors.request.use(config => {
  // 1. 从pinia获取token数据
  const userStore = useUserStore()
  // 2. 按照后端的要求拼接token数据
  const token = userStore.userInfo.token
  if (token) {
    config.headers.Authorization = `Bearer ${token}`
  }
  return config
}, e => Promise.reject(e))

7、退出登录

当用户确认退出登录时,需要清空用户数据并跳转到登录页。以下是详细代码:

import { useUserStore } from '@/stores/userStore'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const router = useRouter()
const confirm = () => {
  console.log('用户要退出登录了')
  // 退出登录业务逻辑实现
  // 1.清除用户信息 触发action
  userStore.clearUserInfo()
  // 2.跳转到登录页
  router.push('/login')
}

下期见~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱学英语的程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值