一.基础配置
1. 路由配置
(1). 创建项目,已经引入了Vue-Router,这里的版本为:3.2.0,并自动创建了router→index.js文件。
(2). 在index.js文件中:
A. 导入vue、vue-router
B. 导入其它子页面
C. 配置路由规则,默认进入/login登录页面,home页面下配置子路由,home页面需要添加路由占位符
<router-view></router-view>
D. 挂载路由导航守卫,token不存在的话,不允许单独跳转到除了login以外的页面,同意跳转到登录页面。
E. 默认对外导出
代码分享:

import Vue from 'vue'
import VueRouter from 'vue-router'
// 导入各个子页面(可以用相对路径 或 根路径,@代表根路径)
import Login from '../components/Login.vue'
import Home from '@/components/Home.vue'
import Welcome from '@/components/Welcome.vue'
import Users from '@/components/user/Users.vue'
import Rights from '@/components/power/Rights.vue'
import Roles from '@/components/power/Roles.vue'
import Params from '@/components/goods/Params.vue'
import GoodsList from '@/components/goods/List.vue'
import Add from '@/components/goods/Add.vue'
import Order from '@/components/order/Order.vue'
import Report from '@/components/report/Report.vue'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [{
path: '/',
redirect: '/login'
},
{
path: '/login',
component: Login
},
{
path: '/home',
component: Home,
redirect: '/welcome',
children: [{
path: '/welcome',
component: Welcome
},
{
path: '/users',
component: Users
},
{
path: '/rights',
component: Rights
},
{
path: '/roles',
component: Roles
},
{
path: '/params',
component: Params
},
{
path: '/goods',
component: GoodsList
},
{
path: '/goods/add',
component: Add
},
{
path: '/orders',
component: Order
},
{
path: '/reports',
component: Report
}
]
}
]
})
// 挂载路由导航守卫
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')
next()
})
// 默认导出
export default router
View Code
PS. 如何手动调用跳转:
this.$router.push('/home')
2. 样式配置
(1). 项目中要用到less语法,所以需要安装less 和 less-loader,开发依赖
【npm install less -D】 (4.1.1)
【npm install [email protected] -D】 (7.3.0)不能装太高版本
(2) style标签中增加 lang="less",表示支持less语法,另外增加scoped属性,代表写的样式仅当前页面有效。
<style lang="less" scoped></style>
3. 静态资源
静态资源,比如全局样式、第三方字体文件等,统一放在 src下的assets文件夹中。然后在main.js文件中导入全局样式和第三方字体。
// 导入字体图标
import './assets/fonts/iconfont.css'
// 导入全局样式表
import './assets/css/global.css'
4. axios封装和使用
(1). 通过指令【npm install axios -save】进行安装
(2). 在main.js中进行导入
(3). 配置baseURL、请求拦截中添加表头(存放token)、利用Vue.prototype进行全局对象封装为$http。
// 导入axios并进行配置
import axios from 'axios'
axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1/'
axios.interceptors.request.use(config => {
// 添加表头信息
config.headers.Authorization = window.sessionStorage.getItem('token');
return config;
})
Vue.prototype.$http = axios
(4).使用:以post请求为例,借助async和await,干掉回调,以同步的编码方式进行获取,然后利用解构赋值,拿到返回对象中的data属性(注意,不是接口返回值的data),然后起别名为res。
async login () {
const {
data: res
} = await this.$http.post('login', this.loginForm)
if (res.meta.status !== 200) return this.$message.error('登录失败!')
this.$message.success('登录成功')
}
5. ESLint警告处理
创建项目的时候,选择安装了ESLint,相关程序集如下:
(1). 运行指令【npm run lint】或者(npm run serve), 会报很多错误和警告,如下图:
但有些警告我们并不像处理,也不想让它提示,那么就在根目录下的 .eslintrc.js 文件中进行关闭
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
// 禁止超过1个空行报错规则,0代表关掉
'no-multiple-empty-lines': 0,
'no-tabs': 0,
'eslint-disable-next-line': 0,
'space-before-function-paren':0,
'indent':0
}
(2). 如果你想更加简单粗暴的关掉验证,可以新增一个.eslintignore文件,直接关掉 .vue文件和 .js文件的验证。
*.vue
*.js
二. 基础组件
1. Form表单
(1). 获取表单对象
在el-form中新加一个ref=“loginFormRef”属性,然后通过 this.$refs.loginFormRef 就可以获取该对象了,可以调用该对象的相关方法。
PS:这是一种通用的方式,适用于任何element组件。
(2). 值绑定
在el-form中通过 :model="loginForm"进行整个对象的绑定,然后在对应 input标签中通过 v-model="loginForm.username"进行子属性的绑定。
(3).验证规则绑定(含自定义验证)
在el-form中通过 :rules="loginFormRules"进行整个验证规则对象的绑定,然后在对应el-form-item标签中通过 prop="属性值" 进行子属性规则的绑定。
PS 自定义验证规则:
需要自定义一个方法,方法有3个参数,rule、value、callback,重点是后两个;value是验证的内容,callback是回调,验证通过,直接返回 callback(); 验证不通过,则声明 callback(new Error('请输入数字值'));
然后定义的方法赋给validator属性。
代码如下:

<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
<script>
export default {
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
View Code
(4). 表单校验
调用validate进行表单内所有内容的校验
this.$refs.loginFormRef.validate(valid => {
console.log(valid)
if (!valid) return
// 下面表示校验通过,进行业务编写
})
(5). 表单重置
this.$refs.loginFormRef.resetFields()
2. Message消息提示
(1). 全局引入和封装
import { Message } from 'element-ui'
Vue.prototype.$message = Message
(2). 使用
this.$message.success('登录成功')
this.$message.error('登录失败!')
或
this.$message({
showClose: true,
message: '错了哦,这是一条错误消息',
type: 'error'
});
三. 登录界面
1. 效果分享
2. 代码分享

<template>
<div class="login_container">
<div class="login_box">
<!-- 头像区域 -->
<div class="avatar_box">
<img src="../assets/logo.png" alt="">
</div>
<!-- 登录表单区域 -->
<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>
</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: {
// 1.重置事件
resetLoginForm () {
// 通过$refs可以达到表单中ref的属性值
this.$refs.loginFormRef.resetFields()
},
// 2. 登录事件
login () {
// 2.1 先对整个form表单进行规则校验
this.$refs.loginFormRef.validate(async valid => {
console.log(valid)
if (!valid) return
// 2.2 校验通过,发送请求
const {
data: res
} = await this.$http.post('login', this.loginForm)
if (res.meta.status !== 200) return this.$message.error('登录失败!')
this.$message.success('登录成功')
// 2.3. 将登录成功之后的 token,保存到客户端的 sessionStorage 中
// 2.3.1 项目中出了登录之外的其他API接口,必须在登录之后才能访问
// 2.3.2 token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中
window.sessionStorage.setItem('token', res.data.token)
// 2.4 通过编程式导航跳转到后台主页,路由地址是 /home
this.$router.push('/home')
})
}
}
}
</script>
<style lang="less" scoped>
.login_container {
background-color: #2b4b6b;
height: 100%;
}
.login_box {
width: 450px;
height: 300px;
background-color: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.avatar_box {
height: 130px;
width: 130px;
border: 1px solid #eee;
border-radius: 50%;
padding: 10px;
box-shadow: 0 0 10px #ddd;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #eee;
}
}
}
.login_form {
position: absolute;
bottom: 0;
width: 100%;
padding: 0 20px;
box-sizing: border-box;
}
.btns {
display: flex;
justify-content: flex-end;
}
</style>
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。