Vue电商项目练习-2 登录页面设计

登录功能实现

  • 登录概述
    • 登录业务流程
    • 登录业务的技术点
    • 登录——token原理分析
  • 具体实现
    • 完成后的效果
    • 创建login组件
      • 1、在components文件夹下创建 Login.vue 文件
      • 2、配置路由实现重定向
      • 3、在 App.vue 组件中放置路由占位符
    • 登录布局设计
      • 1、设置背景色
      • 2、 绘制登录盒子
      • 3、盒子内部设计
      • 4、form 表单组件学习
      • 5、发送登录请求
      • 6、登录后的处理
      • 7、路由导航守卫控制页面访问权限
      • 8、退出登录

登录概述

登录业务流程

  1. 输入用户名和密码
  2. 调用后台接口验证
  3. 根据响应状态跳转到项目主页

登录业务的技术点

  • http是无状态的
  • 通过cookie在客户端记录状态
  • 通过session在服务端记录状态
  • 通过token方式维持状态

登录——token原理分析

服务器根据携带的token值去验证你是哪个用户,根据操作返回不同的结果。token主要进行客户端与服务器端之间身份校验的,token是保证登录成功之后的唯一身份令牌。
Vue电商项目练习-2 登录页面设计_第1张图片

具体实现

完成后的效果

Vue电商项目练习-2 登录页面设计_第2张图片

创建login组件

1、在components文件夹下创建 Login.vue 文件

Login.vue中的script采用以下写法:

<style lang="less" scoped>
</style>

lang=“less” :支持less写法,需要下载less-loader、less(在vue ui依赖中下载)
scoped :样式只在当前组件中有效,避免了各个组件间的样式冲突问题

2、配置路由实现重定向

使用redirect进行路由重定向

const router = new Router({
  routes: [
    { path: '/', redirect: '/login' },
    { path: '/login', component: Login }
  ]
})

3、在 App.vue 组件中放置路由占位符

<template>
  <div id="app">
   <!-- 路由占位符 -->
   <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

登录布局设计

1、设置背景色

<template>
  <div class="login_container">


<style lang='less' scoped>
.login_container {
  background-color: #2b4b6b;
  height: 100%;
}

背景全屏设置:让html、body、最外层盒子高度均为100%。

/* 全局样式表 */
html,
body,
#app {
    height: 100%;
    margin: 0;
    padding: 0;
}

在 main.js 中导入全局样式表

import './assets/css/global.css'   // 导入全局样式表

2、 绘制登录盒子

<template>
  <div class="login_container">
    <div class="login_box">
.login_box {
  height: 300px;
  width: 450px;
  background-color: #fff;
  border-radius: 3px; // 圆角
  position: absolute;
  // 设置居中
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

3、盒子内部设计

图片 + 登录的表单

<template>
  <div class="login_container">
    <div class="login_box">
      <!-- 上部头像图标框 -->
      <div class="image_box">
        <img src="../assets/logo.png" alt="" />
      </div>
      <!-- 登录表单区域 -->
      <el-form
        class="login-form"
        ref="loginFormRef"
        :model="loginForm"
        :rules="loginFormRules"
      >
        <!-- 用户名区域 -->
        <el-form-item prop="username">
          <el-input
            v-model="loginForm.username"
            prefix-icon="el-icon-user"
            size="medium"
          ></el-input>
        </el-form-item>
        <!-- 密码区域 -->
        <el-form-item prop="password">
          <el-input
            v-model="loginForm.password"
            prefix-icon="el-icon-lock"
            size="medium"
            type="password"
          ></el-input>
        </el-form-item>
        <!-- 按钮区域 -->
        <el-form-item class="btns">
          <el-button type="primary" @click="login">登录</el-button>
          <el-button type="info" @click="resetLoginForm">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 登录表单的数据绑定对象
      loginForm: {
        username: "admin",
        password: "123456",
      },
      // 表单的验证规则对象
      loginFormRules: {
        username: [
          { required: true, message: "请输入登录名称", trigger: "blur" },
          {
            min: 3,
            max: 10,
            message: "长度在 3 到 10 个字符",
            trigger: "blur",
          },
        ],
        password: [
          { required: true, message: "请输入登录密码", trigger: "blur" },
          {
            min: 6,
            max: 15,
            message: "长度在 6 到 15 个字符",
            trigger: "blur",
          },
        ],
      },
    };
  },
  methods: {
    // 点击重置按钮,对表单数据进行重置
    resetLoginForm() {
      this.$refs.loginFormRef.resetFields();
    },
    // 对表单进行预验证
    login() {
      this.$refs.loginFormRef.validate((valid) => {
        if (!valid) return;
        this.$http.post("login", this.loginForm).then((res) => {
          if (res.data.meta.status == 200) {
            // 这里前面不能加return
            this.$message.success("登录成功");
            console.log(res);
            // 1 将登录成功之后的token保存到客户端的sessionStorage中
            //     项目中除了登录之外的其他API接口时必须在登录之后才能访问的
            //     token只应当在当前网站打开期间生效,所以将其保存在sessionStorage中
            window.sessionStorage.setItem("token", res.data.data.token);
            // 2 通过编程式导航跳转到后台主页,路由地址是 /home
            this.$router.push("/home");

          } else {
            return this.$message.error("登录失败");
          }
        });
      });
    },
  },
};
</script>
.login_box {
  height: 300px;
  width: 450px;
  background-color: #fff;
  border-radius: 3px; // 圆角
  position: absolute;
  // 设置居中
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);

  .image_box {
    height: 130px;
    width: 130px;
    border: 1px solid #eee;
    border-radius: 50%;
    padding: 10px;
    // box-shadow: 0 0 10px #ddd;
    // 将距离摆正,向右移动login_box的一半减去image_box的一半,向上移动image_box的一半
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
    img {
      width: 100%;
      height: 100%;
      border-radius: 50%;
      background-color: #eee;
    }
  }
}

4、form 表单组件学习

form表单

典型写法:

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="活动名称">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
</el-form>

<script>
  export default {
    data() {
      return {
        form: {
          name: ''
        }
      }
    },

实现效果:
实现效果
:model=“form” 指定的是form表单要绑定的数据,在 data return { } 中定义
v-model=“form.name” 进行表单数据和输入框之间的双向绑定,数据对象中对应的属性

ref=“form” 是整个表单数据的引用,可以用来获取表单数据
:rules=“rules” 是提供表单验证功能,需要在 data return { } 中定义表单验证规则的对象,prop 属性为对应的验证规则字段

自定义表单校验规则
1、定义箭头函数代表校验规则

export default {
  data() {
    // 验证邮箱的规则
    var checkEmail = ( rule, value, callback) => {
      const regEmail = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; 
      if (regEmail.test(value)) {
        // 合法的邮箱
        return callback()
      } else {
        callback(new Error('请输入合法的邮箱'))
      }
    }

2、使用校验规则,通过validator

      // 添加用户的表单验证规则对象
      addFormRules: {
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],

表单数据重置方法
使用 resetFields ,可以通过ref拿到表单的数据,然后调用该方法

this.$refs.loginFormRef.resetFields();

Vue电商项目练习-2 登录页面设计_第3张图片
步骤:

  1. 在表单中添加引用ref=“loginFormRef”
  2. 给重置按钮增加点击监听事件@click=“xxx”
  3. 在处理方法中调用this.$refs.loginFormRef.resetFields()

表单验证

为 el-form 绑定一个验证规则
:rules=“rules” 是提供表单验证功能,需要在 data return { } 中定义表单验证规则的对象,
prop 属性为对应的验证规则中的字段

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  <el-form-item label="活动名称" prop="name">
    <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>

<script>
  export default {
    data() {
      return {
        ruleForm: {
          name: ''
        },
        rules: {
          name: [
            { required: true, message: '请输入活动名称', trigger: 'blur' },
            { min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
          ]}

步骤:

  1. 在data中创建验证规则对象rules
  2. 给表单el-form绑定验证规则对象 使用:rules =“rules”
  3. 给el-form-item项添加 prop=“xxx” ,即表示我们希望使用xxx验证规则验证item里的表单数据项

表单提交前预校验
先拿到表单的引用对象,然后调用 validate 方法
Vue电商项目练习-2 登录页面设计_第4张图片

      this.$refs.loginFormRef.validate((valid) => {
        if (!valid) return;
        this.$http.post("login", this.loginForm).then((res) => {
        });
      });

步骤:

  1. 给表单添加引用
  2. 给登录按钮添加点击事件
  3. 在处理函数中调用validate方法,根据其bool值决定请求/不发起请求

5、发送登录请求

login() {
    this.$refs.loginFormRef.validate(async valid => {
        if (!valid) return;
        //post方法返回一个Promise对象 使用async 函数
        //async表示该函数中有异步操作 await表示后面表达式需要等待结果
        //使用对象解构 并起别名,此时获得的data数据干净
        const { data: res } = await this.$http.post("login", this.loginForm);
        //通过res.meta.status状态码判断请求
        if (res.meta.status === 200) {
            return this.$message.success("登陆成功");
        } else {
            return this.$message.success("登陆失败");
        }
    });
}
    login() {
      this.$refs.loginFormRef.validate((valid) => {
        if (!valid) return;
        this.$http.post("login", this.loginForm).then((res) => {
          if (res.data.meta.status == 200) {
            // 这里前面不能加return
            this.$message.success("登录成功");
            console.log(res);
          } else {
            return this.$message.error("登录失败");
          }
        });
      });
    }

6、登录后的处理

  1. 将登陆成功之后的 token 保存至客户端的 sessionStorage 中
    项目中除了登录之外的其他API接口,必须在登录之后才能访问
    token只应在当前网站打开期间生效,所以放在session里而不是local
  2. 通过路由跳转至后台主页 this.$router.push
		if (res.data.meta.status == 200) {
            // 这里前面不能加return
            this.$message.success("登录成功");
            console.log(res);
            // 1 将登录成功之后的token保存到客户端的sessionStorage中
            //     项目中除了登录之外的其他API接口时必须在登录之后才能访问的
            //     token只应当在当前网站打开期间生效,所以将其保存在sessionStorage中
            window.sessionStorage.setItem("token", res.data.data.token);
            // 2 通过编程式导航跳转到后台主页,路由地址是 /home
            this.$router.push("/home");

          }

新建 Home.vue 组件
然后添加路由规则

{ path: '/home', component: Home}

7、路由导航守卫控制页面访问权限

比如 /HOME 页面是在登录的情况下才允许访问,未登录时不能访问,而跳转到登录页面
Vue电商项目练习-2 登录页面设计_第5张图片
在router/index.js中添加导航守卫

// new 一个router对象,并接收
const router = new Router({
})

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
  // to 表示将要访问的路径
  // from 表示从哪个路径跳转而来
  	// next 是一个函数,表示放行
  	// next() 放行 next('/login) 强制跳转
  if (to.path === '/login') return next()   // 如果访问的是登录页面,直接放行即可
  // 获取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/login')   // 没有token,跳转到登录页面
  next()
})

// 暴露router对象
export default router

8、退出登录

核心原理:清空token,这样后续请求不携带token,必须重新登录生成新token后才能访问页面。

在Home.vue组件中新增退出按钮,实现退出功能

  <el-button type="info" @click="logout">退出</el-button>

  methods: {
    logout() {
      // 清空token 并 跳转到登录页
      window.sessionStorage.clear();
      this.$router.push("/login");
    },

你可能感兴趣的:(前端学习,vue,前端,elementui)