Vue3+axios+Mock.js实现登录功能

1,350 阅读3分钟

前言

这篇文章主要分享一下基于Vue3 + TypeScript的项目,利用Mock.js模拟后端数据,axios实现请求来完成一个登录功能。


一、Vue3 + Element Plus + Mock.js + axios实现登录功能

1.登录页面配置路由、编写表单内容

在router/index.ts中配置路由:

图片1.png

编写登录表单,el-form中绑定的数据要和下面定义的内容保持一致。

图片2.png

效果如下:

图片3.png

2.编写表单校验规则

图片4.png

看下效果:

图片5.png

3.登录触发表单预验证

这里利用Element Plus的form中的validate方法对整个表单进校验。 这个表单节点叫做ruleFormRef,由于setup中是没有this的,我们不能像Vue2中,通过this.$refs.xxx来获取节点。我们去setup中利用ref再重新定义一个相同名称的变量就可以,然后,它们就会自动关联起来。

图片6.png

点击登录就触发校验:

图片7.png

点击登录按钮验证一下:

图片8.png

图片9.png

4.Mock.js模拟登录请求

关于Mock.js的使用,可以看一下之前记录的博客Mock.js学习。在Mock.js中模拟一个post请求,第一个参数是拦截的请求路径,第二个参数是拦截的请求方式,第三个参数是拦截之后的处理逻辑,回调函数中params就是请求体携带的参数。 然后在mock登录请求中限制一下用户名和密码,两者输入正确才能获取到token。token值利用Mock随机函数中来生成。

图片10.png

import Mock from 'mockjs'

// 登录接口
Mock.mock('/admin/login', 'post', (params) =>{
    // 请求参数
    // console.log('post请求传入的参数是:',params.body); //请求体内容  params.body就是post参数
    let loginData = JSON.parse(params.body);

    let data;
    // 用户名和密码正确才会返回token
    if(loginData.username=='admin' && loginData.password=='123456'){
         data = Mock.mock({
            "token": "@id",  // 随机生成一个18位身份证,模拟生成token值
        })
    }

    return {
        status:200,
        message:"请求登录成功!",
        tData:data
    }
});

5.Vue3引入使用axios

安装axios,输入如下命令即可:

npm install axios --save

在Vue3中按照了之前Vue2的写法进行引入挂载全局,会出现报错。

图片11.png

Vue3的写法如下:

图片12.png

直接在登录页面上引入axios,导入axios就可以直接使用啦~ 然后调用一下Mock.js模拟的post登录请求: 在这里插入图片描述 验证一下: 输入正确的账号和密码,就可以获取到请求返回的数据,并且拿到token。 在这里插入图片描述 输入错误的账号密码,就不会返回token值了。 在这里插入图片描述 注意:mock只是模拟数据,不会在network中显示,只有真实的请求才会在network中显示。

登录成功,跳转到首页即可。

router.push("/home");

登录页完整代码如下:

<template>
  <div class="loginContainer">
    <el-form
      ref="ruleFormRef"
      :model="ruleForm"
      :rules="rules"
      class="formStyle"
    >
      <el-form-item label="账号" prop="username">
        <el-input v-model="ruleForm.username" type="text" autocomplete="off" />
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input
          v-model="ruleForm.password"
          type="password"
          autocomplete="off"
        />
      </el-form-item>
      <el-form-item class="loginStyle">
        <el-button type="primary" @click="Login()">登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<!-- script标签中添加setup,那么就不用写setup函数和return了 -->
<script lang="ts" setup>
import { ref, reactive, toRefs } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import Cookies from "js-cookie";

// 表单数据
let ruleForm = reactive({
  username: "",
  password: "",
});

// 获取el-form组件对象    名称和上面表单绑定ref的一样,它们俩就会自动关联起来。
let ruleFormRef = ref();

// 校验密码的函数     传3个参数,并对参数利用ts进行类型约束
// 进行类型约束   rule的类型不确定,就用unknown; 密码是放在输入框的,就是string类型;
// 函数,里面有一个string类型的参数,是可选的
const validatePassword = (
  rule: unknown,
  value: string | undefined,
  callback: (msg?: string) => void
) => {
  // 判断value是否为空,如果value不存在,那么
  if (!value) {
    callback("密码不能为空!");
  } else {
    // 如果不为空,就直接调用函数不提示内容。
    // 由于上面定义函数的参数是可选的,所以调用函数的时候可以不添加参数了
    callback();
  }
};

// 校验规则
const rules = reactive({
  username: [
    { required: true, message: "用户名不能为空!", trigger: "blur" },
  ],
  password: [{ required: true, validator: validatePassword, trigger: "blur" }],
});

// 获取路由对象
let router = useRouter();

// 获取vuex对象    useStore()方法创建store对象   Vue3的store相当于Vue2的this.$store
let store = useStore();

// 登录按钮操作
const Login = () => {
  // 登录触发校验规则
  // 由于ruleFormRef是通过ref定义的,操作它需要利用.value
  // validate是element plus 中form表单的方法,获取到form表单以后就可以直接调用了。
  ruleFormRef.value
    .validate()
    .then(() => {
      // mock模拟请求 
      // 第一个参数是请求路径,第二个参数是携带的请求参数(username password)
      axios
        .post("/admin/login", {
          // 用户名和密码绑定表单的内容
          username: ruleForm.username,
          password: ruleForm.password,
        })
        .then((res) => {
          // console.log(res.data);
          let token = res.data.tData.token;  // 存储token
          // console.log("登录成功获取token值:", token);
          // 登录成功跳转到首页
          router.push("/home");
        });
    })
    .catch(() => {
      // console.log("表单校验不通过");
    });
};
</script>

<style lang="scss" scoped>
.loginContainer {
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

  .formStyle {
    border: 1px solid rgb(236, 225, 225);
    border-radius: 12px;
    padding: 40px;
    box-shadow: 0px 0px 36px rgba(0, 0, 0, 0.1);

    .loginStyle {
      display: flex;
      justify-content: center;
    }
  }
}
</style>


二、面试题

1.前端登录流程

① 在登录页点击”登录“,前端会带着用户名和密码去调用后端的登录接口请求登录; ② 后端收到请求后,会验证用户名和密码,如果验证失败,会返回相关的错误信息,前端提示相应错误信息;如果验证成功,就会生成当前用户所对应的一个token值,并返回前端token; ③ 前端拿到token之后,将token存储起来(可以存储在localStorage、sessionStorage、cookie、vuex中),并跳转页面即登录成功; ④ 前端每一次向后端请求资源的时候都要携带后端签发的token。如果前端在发起下一次请求时携带了token,那么服务器就会根据提交的token值去验证你是哪个用户,从而根据你的操作去返回不同的结果; ⑤ 最后,在向后端发送其他请求时,我们一般需要在请求头中带上这个token值,在项目中我们通常把它封装在一个请求拦截器中,后端判断请求头中有无该token,有则验证该token,验证成功就会正常地返回数据,验证失败,比如过期,就会返回相应的错误码,前端拿到相关错误信息清除token,并且再回退到登录页。

2.token是什么?

token的意思是令牌,是用户第一次登录时,服务器生成的一段加密字符串,然后返回给客户端。 客户端每次向服务器请求资源的时候,只需要带上token去请求数据就行,不用再带着用户名和密码去请求,服务器直接解密token,就可以知道用户的相关信息。由于基本所有请求都需要携带toke,我们可以在请求拦截器中统一封装,让每个请求都能带上token。