一.基础配置
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
PS. 如何手动调用跳转:
this.$router.push('/home')
2. 样式配置
(1). 项目中要用到less语法,所以需要安装less 和 less-loader,开发依赖
【npm install less -D】 (4.1.1)
【npm install less-loader@7.x -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>
(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 { 450px; height: 300px; background-color: #fff; border-radius: 3px; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); .avatar_box { height: 130px; 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 { 100%; height: 100%; border-radius: 50%; background-color: #eee; } } } .login_form { position: absolute; bottom: 0; 100%; padding: 0 20px; box-sizing: border-box; } .btns { display: flex; justify-content: flex-end; } </style>
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。