黑马头条vue2.0项目实战(二)——登录注册功能的实现

news2024/11/18 22:40:34

1. 布局结构

目标

  • 能实现登录页面的布局

  • 能实现基本登录功能

  • 能掌握 Vant 中 Toast 提示组件的使用

  • 能理解 API 请求模块的封装

  • 能理解发送验证码的实现思路

  • 能理解 Vant Form 实现表单验证的使用

这里主要使用到三个 Vant 组件:

  • NavBar 导航栏

  • Form 表单

    • Field 输入框

    • Button 按钮

1.1 布局样式

        写样式的原则:将公共样式写到全局(src/styles/index.less),将局部样式写到组件内部。对于需要更改样式,自己添加 class 类名。

1.2 自定义图标的使用

官方文档实现:

实现效果:

最左侧显示的图标无法满足需求的情况下,可以通过 slot 实现,插入自定义的图标。可以插入的slot如下所示:

具体实现,通过插入 i 标签,设置 iconfont 类名。

1.2 插入按钮

官方文档:

实现效果:

        但是在表单中,除了提交按钮外,可能还有一些其他的功能性按钮,如发送验证码按钮。在使用这些按钮时,要注意将 native-type设置为button,否则会触发表单提交。

2. 实现基本登录功能

功能需求:

  • 注册点击登录的事件

  • 获取表单数据(根据接口要求使用 v-model 绑定)

  • 表单验证

  • 发请求提交

  • 根据请求结果做下一步处理

2.1 登录状态提示

2.2 表单验证

  •  给 vant-field 组件配置 rules 验证规则     

  • 可以在 data 里自定义校验规则校验手机号和验证码

  • 当给表单提交的时候会自动触发表单验证
    • 如果验证通过,则触发 submit 事件
    • 如果验证不通过,则不会触发 submit 事件
    • 验证规则 参考vant组件的文档

2.3 验证码处理

点击发送验证码功能

功能需求:

  • 点击发送验证码按钮后,对用户输入的手机号进行验证

  • 验证通过显示倒计时

  • 发送用户手机号给后端,后台给用户手机下发验证码
  • 发送失败关闭倒计时

注意:

  • 这里的 ref 是绑在表单 Form上
  • 获取表单实例之后,通过 .validate('校验表单或输入框的name属性值')
  • 返回的是一个 promise 对象

3. 处理用户 Token

Token 是用户登录成功之后服务端返回的一个身份令牌,在项目中的多个业务中需要使用到:

  • 访问需要授权的 API 接口

  • 校验页面的访问权限

  • ...

但是我们只有在第一次用户登录成功之后才能拿到 Token。

所以为了能在其它模块中获取到 Token 数据,我们需要把它存储到一个公共的位置,方便随时取用。

往哪儿存?

  • 本地存储

    • 获取麻烦

    • 数据不是响应式

  • Vuex 容器(推荐)

    • 获取方便

    • 响应式的

3.1 使用容器存储 Token 的思路

  • 登录成功,将 Token 存储到 Vuex 容器中

    • 获取方便

    • 响应式

  • 为了持久化,还需要把 Token 放到本地存储

    • 持久化

登录成功以后将后端返回的 token 相关数据存储到容器中

3.2 优化封装本地存储操作模块

创建 src/utils/storage.js 模块

3.3 关于 Token 过期问题

登录成功之后后端会返回两个 Token:

  • token:访问令牌,有效期2小时

  • refresh_token:刷新令牌,有效期14天,用于访问令牌过期之后重新获取新的访问令牌

我们的项目接口中设定的 Token 有效期是 2 小时,超过有效期服务端会返回 401 表示 Token 无效或过期了。

为什么过期时间这么短?

  • 为了安全,例如 Token 被别人盗用

过期了怎么办?

  • 让用户重新登录,用户体验太差了

  • 使用 refresh_token 解决 token 过期

后续拓展 Token 过期处理 ,在学习测试的时候如果收到 401 响应码,请重新登录再测试

概述:服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的 token 过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401。

处理流程:

  1. 在axios的拦截器中加入token刷新逻辑

  2. 当用户token过期时,去向服务器请求新的 token

  3. 把旧的token替换为新的token

  4. 然后继续用户当前的请求

在请求的响应拦截器中统一处理 token 过期(后续拓展)。

/**
 * 封装 axios 请求模块
 */
import axios from "axios";
import jsonBig from "json-bigint";
import store from "@/store";
import router from "@/router";

// axios.create 方法:复制一个 axios
const request = axios.create({
  baseURL: "http://ttapi.research.itcast.cn/" // 基础路径
});

/**
 * 配置处理后端返回数据中超出 js 安全整数范围问题
 */
request.defaults.transformResponse = [
  function(data) {
    try {
      return jsonBig.parse(data);
    } catch (err) {
      return {};
    }
  }
];

// 请求拦截器
request.interceptors.request.use(
  function(config) {
    const user = store.state.user;
    if (user) {
      config.headers.Authorization = `Bearer ${user.token}`;
    }
    // Do something before request is sent
    return config;
  },
  function(error) {
    // Do something with request error
    return Promise.reject(error);
  }
);

// 响应拦截器
request.interceptors.response.use(
  // 响应成功进入第1个函数
  // 该函数的参数是响应对象
  function(response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  },
  // 响应失败进入第2个函数,该函数的参数是错误对象
  async function(error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
    // 如果响应码是 401 ,则请求获取新的 token

    // 响应拦截器中的 error 就是那个响应的错误对象
    console.dir(error);
    if (error.response && error.response.status === 401) {
      // 校验是否有 refresh_token
      const user = store.state.user;

      if (!user || !user.refresh_token) {
        router.push("/login");

        // 代码不要往后执行了
        return;
      }

      // 如果有refresh_token,则请求获取新的 token
      try {
        const res = await axios({
          method: "PUT",
          url: "http://ttapi.research.itcast.cn/app/v1_0/authorizations",
          headers: {
            Authorization: `Bearer ${user.refresh_token}`
          }
        });

        // 如果获取成功,则把新的 token 更新到容器中
        console.log("刷新 token  成功", res);
        store.commit("setUser", {
          token: res.data.data.token, // 最新获取的可用 token
          refresh_token: user.refresh_token // 还是原来的 refresh_token
        });

        // 把之前失败的用户请求继续发出去
        // config 是一个对象,其中包含本次失败请求相关的那些配置信息,例如 url、method 都有
        // return 把 request 的请求结果继续返回给发请求的具体位置
        return request(error.config);
      } catch (err) {
        // 如果获取失败,直接跳转 登录页
        console.log("请求刷新 token 失败", err);
        router.push("/login");
      }
    }

    return Promise.reject(error);
  }
);

export default request;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1955421.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

windows 安装 Linux 子系统 Ubuntu,并编译安装nginx

1. 安装Ubuntu 首先可以在 Microsoft Store 自行搜索安装 Ubuntu,个人建议安装 22 版本的即可。Ubuntu安装完成后,以管理员身份打开CMD,运行如下命令: wsl --install 此时打开Ubuntu已经可以正常使用了。 2. 安装C/C编译器 对于…

动态规划专题:线性dp、背包问题,区间

目录 方块与收纳盒 舔狗舔到最后一无所有 可爱の星空 数字三角形 花店橱窗 [NOI1998]免费馅饼 [NOIP2002]过河卒 [NOIP2008]传球游戏 「木」迷雾森林 [NOIP2004]合唱队形 [NOIP1999]拦截导弹 数学考试 小A买彩票 购物 牛牛的旅游纪念品 [NOIP2001]装箱问题 [N…

网络轮询器 NetPoller

网络轮询器 NetPoller 网络轮询器是 Go 语言运行时用来处理 I/O 操作的关键组件,它使用了操作系统提供的 I/O 多路复用机制增强程序的并发处理能力。网络轮询器不仅用于监控网络 I/O,还能用于监控文件的 I/O,它利用了操作系统提供的 I/O 多路…

How can I fix my Flask server‘s 405 error that includes OpenAi api?

题意:解决包含OpenAI API的Flask服务器中出现的405错误(Method Not Allowed,即方法不允许) 问题背景: Im trying to add an API to my webpage and have never used any Flask server before, I have never used Java…

MATLAB进阶:函数和方程

经过前几天的学习,matlab基础我们已经大致了解,现在我们继续学习matlab更进一步的应用。 常用函数 在求解有关多项式的计算时,我们无可避免的会遇到以下几个函数 ypolyval(p,x):求得多项式p在x处的值y,x可以是一个或…

ComfyUI反推提示词节点报错:Load model failed

🎠报错现象 反推提示词的时候会提示报错: Error occurred when executing WD14Tagger|pysssss: [ONNXRuntimeError] : 3 : NO_SUCHFILE : Load model from F:\ComfyUI-aki\custom_nodes\ComfyUI-WD14-Tagger\models\wd-v1-4-convnext-tagger-v2.onnx fa…

创建mysql库,及webserver使用编译

首先安装mysql sudo apt update sudo apt install mysql-server sudo systemctl status mysql #检查mysql是否安装成功 sudo mysql #进入mysqlSHOW DATABASES; create database yourdb; #创建一个名为yourdb的数据库USE yourdb; #使用刚才创建好的数据库 CREATE TABLE …

Go语言----reflect.DeepEqual函数

在使用go语言进行编程的时候,我们通常会对模块进行测试,在测试的过程中,经常会使用reflect.DeepEqual函数,这个函数是在reflect包中,其提供了运行时反射机制的标准库。其中的reflect.DeepEqual()函数是用来比较两个值是…

【知识梳理】Shell的变量计算

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 Shell中有很多变量的计算,会用到多种运算符。例如这几种: 1. Shell中常见的算术运算符 运算符意义&…

springboot-定时任务源码分析

springboot-定时任务源码分析 前言我们都知道开启 springboot的定时任务需要先使用 EnableScheduling 注解,在可以开启,那么 EnableScheduling 就是定时任务的源头,所以先从 EnableScheduling 开始分析 EnableScheduling 这个注解核心就是…

基于cubeMX的STM32的定时器使用

1、设置cubeMX 这里使用STM32F103RCT6芯片,以定时器2为例,时钟源选择内部时钟 参数设置,预分频7200,定时器周期10000,则表示定时1秒钟 打开定时器2通用中断 其他设置不用修改。时钟页面配置如下 最后生成代码。 2、在…

05.java中常用的类

1.包装类 基本类型包装类booleanBooleancharCharacterbyteByteintIntegerlongLongfloatFloatdoubleDoubleshortShort 从byte开始的包装类都是继承的Number,然后Number继承的object 从byte上面的都是直接继承的oblect (1).装箱和拆箱 装箱:基本类型--…

DSP教学实验箱_数字图像处理操作_案例分享:5-13 灰度图像二值化

一、实验目的 学习灰度图像二值化的原理,掌握图像的读取方法,并实现在LCD上显示二值化前后的图像。 二、实验原理 图像二值化 图像的二值化处理就是将图像上的点的灰度置为 0 或 255,也就是将整个图像呈现出明显的黑白效果。即将 256 个亮…

JAVA零基础学习3(Scanner类,字符串,StringBuilder,StringJoinder,ArrayList成员方法)

JAVA零基础学习3 Scanner类输入示例代码代码解释完整代码1. 读取字符串2. 读取整数3. 读取浮点数4. 读取布尔值5. 读取单个单词6. 读取长整型数7. 读取短整型数8. 读取字节数注意事项总结 API 字符串解释示例解释解决方法示例:使用 StringBuilder String…

阻塞队列-PriorityBlockQueue

PriorityBlockingQueue 优先级队列不满足FIFO原则它将插入元素进行排序排序的实现是基于数组结构实现的二叉堆排序 二叉堆 在分析优先级别队列时候,需要了解一下二叉堆是什么 二叉堆是一种完全二叉树,除了最底层外,其它层被完全填充。二叉堆…

【AI学习指南】轻量级模型-用 Ollama 轻松玩转本地大模型

目录 探索 最小的AI模型 发现 其他轻量级模型 用 Ollama 轻松玩转本地大模型 本地大模型 Ollama 快速上手 安装 手动安装 下载ollama二进制文件 添加 Ollama 作为启动服务(推荐) 安装 CUDA 驱动程序(可选 - 适用于 Nvidia GPU) 安装 ROCm(可选 - 对于 Radeo…

飞腾2000+/64核芯片ECC功能验证

1、背景介绍 为了排查全国产飞腾计算模块的一个外场问题,需要验证飞腾2000/64核这个处理器的DDR控制器是否支持ECC功能,即在异常情况下能纠错。ECC纠错原理如下,目前飞腾2000/64 DDR控制器就是纠一检二: 2、寄存器说明 目前飞腾…

【学习过程总结】

一、二进制和十进制的转化 1、十进制转化为二进制 2、二进制转化为十进制 二进制转化为十进制这个,对于二进制的数,得从右往左看(1《0《1《1)。对于下面的转换过程得从下往上看 (0、1、2、3) 二、按位-异…

原理图----备份

从公司学到的电路图,做一个备份:

用Python做一个翻译软件,比上浏览器快100倍

简单的用Python来做一个翻译软件 开发环境 Python 3.10 Pycharm模块使用 requests -> pip install requests hashlib tkinter案例分为三部分: 1. 爬虫: 获取翻译接口, 请求获取翻译结果问题1: 接口抓包分析问题2: 请求需要写cookie问题3: 不同文本翻译, s加密参数2. 界面…