Vue + element-ui后台管理项目—登录/退出功能

相关配置

打开项目之后
1.打开终端输入 git status 查看一下当前工作区是否干净
2.创建新分支git checkout -b xxx,在实际开发中,当开发一个新功能时,尽量把新功能放到新分支去进行开发
3.查看当前所有分支 git branch 其中带星号的是当前所处的分支

PS G:\vue-cli\vue_shop> git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

PS G:\vue-cli\vue_shop> git checkout -b login
Switched to a new branch 'login'

PS G:\vue-cli\vue_shop> git branch
* login
  master

接着查看一下项目的运行效果,打开vue可视化面板,在任务里面运行serve这个命令
若显示运行中止:
在这里插入图片描述
打开babel.config.js文件查看element-ui插件是否重复,删除后保存重新运行
在这里插入图片描述
接着将App根组件、router/index.js文件不必要的组件和代码删除,将views文件夹、components文件夹中HelloWorld根组件删除

新建登录组件
  • 在Components文件夹中新建组件MyLogin.vue,注意驼峰命名法,否则会报错:error: Component name “xxx” should always be multi-word.
<template>
  <div>登录组件</div>
</template>

<script>
export default {
  name: "Login",
};
</script>

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

  • 在route/index.js文件中通过路由的形式把它渲染到App根组件中
  • 先导入MyLogin组件
import MyLogin from '../components/MyLogin.vue'
  • 然后在路由规则数组中导入一个新的路由规则
routes: [
    { path: '/mylogin', component: MyLogin }
  ]
  • 在App根组件中放置一个路由占位符 <router-view>,这样通过路由匹配到的这些组件都会被渲染到router-view里被展示
<template>
  <div id="app">
   <!-- 路由占位符 -->
   <router-view></router-view>
  </div>
</template>
  • 访问根组件时自动重定向到login组件中
 routes: [
    { path: '/', redirect: '/mylogin' },
    { path: '/mylogin', component: MyLogin }
  ]
  • 添加一个class类
<div class="login_container">
        登录组件
    </div>

在样式中加类选择器后运行时出现报错:
在这里插入图片描述
则需要在此之前下载好less和less-loader,在终端输入命令:

npm install less less-loader --save-dev
npm install less --save-dev

或在vue图形化界面里安装开发依赖
在这里插入图片描述
然后重新运行项目,此时编译成功
若仍然有报错检查webpack是否安装成功,可以借鉴@水w博主的这篇博客

登录功能的实现

通过 Element-UI 组件来实现布局

  • el-form:整个登录框是一个form
  • el-form-item:用户名,密码,登录和重置按钮都属于表单item项,有3个
  • el-input
  • el-button
  • 字体图标
一、绘制登录组件头部区域
<!-- 头像区域 -->
<div class="avatar_box">
    <img src="../assets/logo.png" alt="">
</div>
.avatar_box{
    height: 130px;
    width: 130px;
    border: 1px solid #eee;
    border-radius: 50%;
    padding: 10px;
    box-shadow: 0 0 10px #ddd; //阴影向外扩散10px
    position: absolute;
    left: 50%;
    transform: translate(-50%, -50%);
    background-color: #fff;
    img{
        width: 100%;
        height: 100%;
        border-radius: 50%;
        background-color: #eee;
    }
}

在这里插入图片描述

二、绘制登录组件表单区域

使用Element-UI 组件
在plugins/element.js文件中导入所需的Element-UI组件并注册为全局可用的组件

import Vue from 'vue'
import { Button, Form, FormItem, Input } from 'element-ui'

Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
<!-- 登录表单区域 -->
<el-form label-width="0px" class="login_form">
    <!-- 用户名 -->
    <el-form-item>
        <el-input></el-input>
    </el-form-item>
    <!-- 密码 -->
    <el-form-item>
        <el-input></el-input>
    </el-form-item>
    <!-- 按钮 -->
    <el-form-item class="btns">
        <el-button type="primary">登录</el-button>
        <el-button type="info">重置</el-button>
    </el-form-item>
</el-form>
.login_form{
    position: absolute;
    bottom: 0;
    width: 100%; //文本框占满整个区域
    padding: 0 20px;
    box-sizing: border-box; //默认是content-box,改为border-box使设置的边框和内边距的值包含在width内
}
.btns{ //按钮靠右侧
    display: flex;
    justify-content: flex-end;
}

在这里插入图片描述

三、添加登录组件表单小图标

在element ui组件库中找到input输入框里带icon的输入框,使用prefix-icon 属性在 input 组件添加前置小图标,素材通过外部引入,将fonts文件夹放入assets文件夹中,在main.js文件中导入字体图标。

<!-- 用户名 -->
<el-form-item>
    <el-input prefix-icon="iconfont icon-user"></el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item>
    <el-input prefix-icon="iconfont icon-3702mima"></el-input>
</el-form-item>
四、登录组件表单的数据绑定

通过属性绑定给el-form绑定一个model属性,值是一个数据对象,在data中做定义,为每一个具体表单项通过v-model属性双向绑定到数据对象上对应的属性中

<!-- 登录表单区域 -->
<el-form :model="loginForm" label-width="0px" class="login_form">
    <!-- 用户名 -->
    <el-form-item>
       <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
    </el-form-item>
    <!-- 密码 -->
    <el-form-item>
       <el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima" type="password"></el-input> 
       <!-- 注意加一个type属性把密码隐藏 -->
    </el-form-item>
   
<script>
export default {
  data () {
    return {
      // 这是登录表单的数据绑定对象
      loginForm: {
        username: 'zs',
        password: '123'
      }
    }
  }
}
</script>
五、为登录组件表单添加验证规则

1.为el-form通过属性绑定绑定一个rules校验规则对象
2.在data数据中,定义这个校验对象的验证规则属性
3.为不同的表单item项通过prop指定不同的验证规则,来进行表单的验证
注意:验证规则是加给item,而不是文本框

 <!-- 登录表单区域 -->
<el-form :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
  <!-- 用户名 -->
  <el-form-item prop="username">
     <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
  </el-form-item>
  <!-- 密码 -->
     <el-form-item prop="password">
         <el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima" type="password"></el-input> <!-- 注意加一个type属性把密码隐藏 -->
     </el-form-item>
     
<script>
export default {
  data () {
    return {
      // 这是登录表单的数据绑定对象
      loginForm: {
        username: 'zs',
        password: '123'
      },
      // 这是表单的验证规则对象
      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' }
        ]
      }
    }
  }
}
</script>

                
六、登录组件表单的重置

在这里插入图片描述
1.为这个表单添加一个ref引用,它的值就是组件的实例对象
2.给重置按钮绑定一个@click点击事件
3.紧接着可以通过this访问到$refs,访问表单的引用对象,调用resetFields函数方法

<!-- 登录表单区域 -->
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
   <!-- 用户名 -->
   <el-form-item prop="username">
      <el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
   </el-form-item>
   <!-- 密码 -->
   <el-form-item prop="password">
       <el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima" type="password"></el-input> <!-- 注意加一个type属性把密码隐藏 -->
    </el-form-item>
    <!-- 按钮 -->
    <el-form-item class="btns">
       <el-button type="primary">登录</el-button>
       <el-button type="info" @click="resetLoginForm">重置</el-button>
     </el-form-item>
</el-form>

<script>
export default {
  data () {
    return {
      // 这是登录表单的数据绑定对象
      loginForm: {
        username: 'zs',
        password: '123'
      },
      // 这是表单的验证规则对象
      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 () {
      console.log(this) // 这里this就指向登录组件的实例对象
      this.$refs.loginFormRef.resetFields()
    }
  }
}
</script>
七、实现登录组件登录前的预验证

在这里插入图片描述
1.给登录按钮绑定一个@click点击事件
2.先获取到表单的引用对象,通过这个引用对象可以调用validate函数进行表单的预校验
3.在validate中接收一个回调函数,第一个形参是验证结果 布尔值,可以通过判断这个布尔值来判断表单是否通过验证

<script>
export default {
  data () {
    return {
      // 这是登录表单的数据绑定对象
      loginForm: {
        username: 'zs',
        password: '123'
      },
      // 这是表单的验证规则对象
      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 () {
      console.log(this) // 这里this就指向登录组件的实例对象
      this.$refs.loginFormRef.resetFields()
    },
    // 点击登录按钮,进行登录前的预验证
    login () {
      this.$refs.loginFormRef.validate(valid => { // 这个箭头函数只要一个形参 所以省略小括号
        console.log(valid)
      })
    }
  }
}
</script>
八、登录组件根据预验证判断是否发起请求

在具体请求之前,应该在入口文件main.js中,对axios进行全局配置
先导入axios包,把axios包挂载到vue的原型对象上,这样每一个vue的组件都可以通过this直接访问到原型上的$http ,从而去发起ajax请求,当挂载完这个原型的属性之后,为axios设置一下请求的根路径

import axios from 'axios'
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios

在Navicat中连接Mysql数据库,用node执行app.js;
先判断valid是否为true,如果为true’发起请求,如果不为true阻止这次请求;
通过$http发起post请求,请求地址login,请求对象this.loginForm(loginForm是登录表单的数据绑定对象,用户在el-form中填写的数据都会自动同步到loginForm中),接收后打印result,返回值是Promise,如图

login () {
      this.$refs.loginFormRef.validate(valid => { // 这个箭头函数只要一个形参 所以省略小括号
        if (!valid) return {}
        const result = this.$http.post('login', this.loginForm)
        console.log(result)
      })
    }

在这里插入图片描述
如果某个方法的返回结果是Promise,我们可以用async await来简化这次Promise操作,注意await只能用在被async修饰的方法中,所以应该把await外面的这个方法也就是箭头函数修饰成异步函数

login () {
      this.$refs.loginFormRef.validate(async valid => { // 这个箭头函数只要一个形参 所以省略小括号
        if (!valid) return {}
        const result = await this.$http.post('login', this.loginForm)
        console.log(result)
      })
    }

在这里插入图片描述

经过分析,服务器返回的对象中包含了6个属性,其中data才是服务器返回的真实数据,因此从这个数据对象身上把data属性解构赋值出来,同时重命名为res对象

login () {
      this.$refs.loginFormRef.validate(async valid => { // 这个箭头函数只要一个形参 所以省略小括号
        if (!valid) return {}
        const { data: res } = await this.$http.post('login', this.loginForm)
        console.log(res)
      })
    }

if判断res里面mata的状态码,如果状态码是200 就是登录失败,如果没有return就是登录成功

login () {
      this.$refs.loginFormRef.validate(async valid => { // 这个箭头函数只要一个形参 所以省略小括号
        if (!valid) return {}
        const { data: res } = await this.$http.post('login', this.loginForm)
        // console.log(res)
        if (res.meta.status !== 200) return console.log('登录失败')
        console.log('登录成功')
      })
    }

在这里插入图片描述

九、登录组件配置弹窗提示

使用Element UI组件库中提供的 Message 消息提示
在element.js文件中,从element-ui导入弹框提示组件Message,弹框提示组件需要进行全局挂载,把弹框属性挂载到vue原型对象上,这样每一个组件都可以通过this访问到$message 来进行弹框提示

import Vue from 'vue'
import { Button, Form, FormItem, Input, Message } from 'element-ui'

Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.prototype.$message = Message // $message是自定义属性,名称只要合法就行

在myLogin.vue文件中,this访问到$ message属性,$ message上提供了一系列弹框方法,error是代表错误,succes是正确提示框

login () {
      this.$refs.loginFormRef.validate(async valid => { // 这个箭头函数只要一个形参 所以省略小括号
        if (!valid) return {}
        const { data: res } = await this.$http.post('login', this.loginForm)
        // console.log(res)
        if (res.meta.status !== 200) return this.$message.error('登录失败!')
        this.$message.success('登录成功!')
      })
    }

在这里插入图片描述

十、登录成功后的操作行为

将登录成功之后服务器颁发的 token 信息保存到客户端的 sessionStorage 中

  • 项目中除了登录之外的其他API接口,必须在登录之后才能访问成功
  • token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中
window.sessionStorage.setItem('token', res.data.token)

通过编程式导航跳转到后台主页,$router编程式导航对象调用push方法,路由地址是 /home

this.$router.push('/home')

创建一个home页面 Components文件夹中新建Home.vue组件
找到路由规则router/index.js,导入Home组件,新建一个路由规则

import Vue from 'vue'
import VueRouter from 'vue-router'
import myLogin from '../components/myLogin.vue'
import Home from './components/Home.vue'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/mylogin' },
    { path: '/mylogin', component: myLogin },
    { path: '/home', component: Home }
  ]
})

export default router

十一、路由导航守卫控制访问权限

如果用户没有登录,但是直接通过URL访问到了特定页面,需要重新导航到登录页面home是一个有权限的页面,只有登录成功之后才可以被访问
我们希望用户从home路径直接跳转到login登录页

挂载路由导航守卫:为router对象调用一个beforeEach函数,beforeEach函数接收一个箭头函数

// 挂载路由导航守卫
router.beforeEach((to, from, next) => {
  // to 将要访问的路径
  // from 代表从哪个路径跳转而来
  // next 是一个函数 表示放行
  // next() 放行
  // next('/login') 强制跳转

  // 路由导航守卫的控制
  // 判断用户访问的是不是登录页
  if (to.path === '/mylogin') return next()
  // 获取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/mylogin')
  next()
})

退出功能的实现

基于 token 的方式实现退出比较简单,只需要销毁本地的 token 即可,这样后续的请求就不会携带 token,必须重新登录生成一个新的 token 之后才可以访问页面

在Home.vue文件中添加一个button按钮,绑定一个点击事件logout
在logout调用期间首先清空sessionStorage,接着重定向到登录页面

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

<script>
export default {
  methods: {
    logout () {
      window.sessionStorage.clear()
      this.$router.push('/mylogin')
    }
  }
}
</script>

<style lang="less" scoped>
</style>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ensie_Liang

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

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

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

打赏作者

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

抵扣说明:

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

余额充值