文章目录
相关配置
打开项目之后
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>