【Vue.js+Element UI+ Node.js】实现登录验证
1.配置主页和登录页的路由router
/src/main.js
import Vue from 'vue'
// 引入Element UI组件
import ElementUI from 'element-ui'
// 引入Element UI样式文件
import 'element-ui/lib/theme-chalk/index.css'
import App from './App'
import router from './router'
// 引入reset.css
import './assets/css/reset.css'
// 使用Element UI(注册组件)
Vue.use(ElementUI)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
/src/router/route.js
const routes = [
{
path: '/',
name: 'Index',
component: () => import('@/pages/main/Index')
},
{
path: '/login',
name: 'login',
component: () => import('@/pages/login/Index'),
meta: {
title: 'Login'
}
}
]
export default routes
2.路由拦截
- 设置页面标题
- 如果要跳转的页面不是登录页面,就必要登录成功之后才能访问
- 跳转的就是登录页面,不做拦截
/src/router/index.js
import Vue from 'vue'
import Router from 'vue-router'
// 导入路由规则
import routes from './routes'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes
})
// 拦截
router.beforeEach((to, from, next) => {
// console.log(to.meta)
// 设置页面标题
document.title = to.meta.title || 'United Mall Backend Management System'
// 如果要跳转的页面不是登录页面,就必须要登录成功之后才能访问
if (to.path === '/login') {
// 跳转的就是登录页面,不做拦截
next()
} else {
// 跳转的不是登录页面,需要登录以后才能够访问到
const userInfo = sessionStorage.getItem('user')
if (!userInfo) {
// 没有登录,则跳转登录页面
next('/login')
} else {
next()
}
}
})
export default router
3.利用Element-UI组件完成登录页的样式设置和表单验证
/src/pages/login/Index.vue
<template>
<div class = "main">
<div class="loginform">
<h3 class="title">管理员登录</h3>
<el-form ref="form" :model="loginInfo" :rules = "rules">
<el-form-item label="" prop = "username">
<el-input v-model="loginInfo.username" placeholder="请输入账号" clearable>
<template slot="prepend">
<i class="el-icon-s-custom"></i>
</template>
</el-input>
</el-form-item>
<el-form-item label="" prop = "password">
<el-input v-model="loginInfo.password" placeholder="请输入密码" show-password clearable>
<template slot="prepend">
<i class="el-icon-lock"></i>
</template>
</el-input>
</el-form-item>
<el-form-item label="">
<el-button type="primary" @click="onSubmit" class="loginbtn">登录</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
// 从user中导出登录方法
import { login } from '@/api/user'
export default {
data () {
return {
loginInfo: {
username: '',
password: ''
},
rules: {
// 规则的编写
username: [
{ required: true, message: '请输入账号', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' }
]
}
}
},
methods: {
onSubmit () {
// console.log('on submit')
// 触发表单验证 调用Form组件的validate回调方法
this.$refs.form.validate(valid => {
// validate表示验证是否全部通过
// console.log('valid', valid)
if (valid) {
// 全部通过
this.login()
}
})
},
login () {
// 登录处理
login(this.loginInfo.username, this.loginInfo.password).then(res => {
// console.log(res)
// 登录成功, 把返回的信息保存到sessionStorage中
sessionStorage.setItem('user', JSON.stringify(res))
// 跳转到后台首页
this.$router.replace('/')
}).catch(err => {
// console.error(err.message)
// 登录失败,显示错误信息
this.$message.error(err.message)
})
}
}
}
</script>
<style scoped>
.main {
width: 100%;
height: 100%;
background: url('~@/assets/images/loginbg.jpg') no-repeat;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
}
.loginform {
background: #ffffff;
padding:18px 28px;
border-radius: 10px;
}
.loginform .title {
font-size: 18px;
font-weight: 700;
text-align: center;
margin-bottom: 20px;
}
.loginform .loginbtn {
width:100%
}
</style>
4.解决跨域问题,配置代理
config/index.js
// 代理配置
proxyTable: {
"/api":{
target:"http://localhost:3000",
changeOrigin: true,
pathRewrite:{
// url路径重写
"^/api": "/api"
}
}
},
5.配置接口文件,
/src/api/http.js
import axios from 'axios'
// 1.创建一个axios实例, 不污染全局的axios对象
const http = axios.create({
baseURL: '/api', // 会产生所有的axios的url前添加/api
timeout: 5000 // 超时的时间
})
// 2.响应拦截
http.interceptors.response.use(function (response) {
response = response.data
// console.log('http interceptors', response)
if (response.code === 200) { // 接口请求成功(包括数据正常返回)
return response.list || null
}
return Promise.reject(new Error(response.msg))
}, function (error) {
return Promise.reject(error)
})
export default http
6.封装登录方法
/src/user.js
import http from './http'
// 登录
export const login = (username, password) => {
if (!username || !password) {
return Promise.reject(new Error('账号或密码为空'))
}
return http.post('/userlogin', {
username,
password
})
}
7.登录
- 登录成功, 把返回的信息保存到sessionStorage中
- 登录成功,跳转到后台首页
- 登录失败,显示错误信息
login () {
// 登录处理
login(this.loginInfo.username, this.loginInfo.password).then(res => {
// console.log(res)
// 登录成功, 把返回的信息保存到sessionStorage中
sessionStorage.setItem('user', JSON.stringify(res))
// 跳转到后台首页
this.$router.replace('/')
}).catch(err => {
// console.error(err.message)
// 登录失败,显示错误信息
this.$message.error(err.message)
})
}
8.退出登录
退出登录时清除本地存储中的登录用户信息,并跳转登录页面
/components/Header.vue
<template>
<div class="header">
<div class="logo">United Mall后台管理系统</div>
<!-- 下拉菜单选项
divided 添加横线
disabled 禁用 -->
<el-dropdown @command = "handleCommand">
<span class="el-dropdown-link">
欢迎!{{username}}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command = "personInfo">个人信息</el-dropdown-item>
<el-dropdown-item command = "changePwd">修改密码</el-dropdown-item>
<el-dropdown-item divided command = "logout">退出系统</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</template>
<script>
export default {
data () {
return {
username: ''
}
},
mounted () {
// 从本地存储中获取登录用户的信息
const userInfo = JSON.parse(sessionStorage.getItem('user'))
this.username = userInfo.username // 获取登录用户的账号
// console.log(userInfo)
},
methods: {
handleCommand (command) {
// console.log('command', command)
// 必须保证command和对应的方法名称相同
this[command]()
},
personInfo () {
console.log('personal info')
},
changePwd () {
console.log('change password')
},
logout () {
console.log('log out')
// 退出系统
// 清除本地存储中的登录用户信息
sessionStorage.removeItem('user')
// 跳转登录页面
this.$router.replace('/login')
}
}
}
</script>
<style scoped>
.header {
width: 100%;
height: 100%;
background: #518ecb;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
box-sizing: border-box;
}
.logo {
font-size: 20px;
font-weight: 700;
color: #ffffff;
}
.el-dropdown-link {
color: #ffffff;
}
</style>