前言:
作为一个刚刚接触前端一个半月的菜鸟Yang来说,学习吸收知识太快缺少实践会导致地基不牢固,例如axios,http,vuex,vue-router等
速度快的代价就是菜,所以Yang决定在期末考试周每天抽出点时间做一套完整的管理系统的登录注册切换和axios的封装(token) --表单组件使用element ui
另外保佑自己高数不挂科,一个学期悟出的真理:大学期末===高四 (ó﹏ò。)
--简易版于1月10日完成,本文做以小结,勉励自己(萌新摸索记录)--接下来学习权限登录
实现的功能:vue2的登录注册功能基本实现及表单切换和axios的封装(token)
功能实现三部曲:
- axios的封装以及token的携带
- element ui中form实现登录注册和登录注册按钮表单切换
- vue-router完善登录页面和注销功能
正文:
1. axios的封装以及token的携带
新手眼中的难点(我):
- axios中interceptors拦截器的使用:interceptor.response.use响应拦截和interceptor.request.use请求拦截
- 请求头是什么??(http基础,被工作室学长提醒基础不稳,假期一定好好补基础!)
- token的作用存储token的方法
- 从未接触过status状态码,以及code是啥玩意?
- token过期(还没用到)QWQ
我的摸索:
- 响应拦截器和请求拦截器可以更改对状态码和code进行判断,然后选择是否返回——错误返回空,正确把res返回成res.data
- 响应拦截器response的参数有response和error
- 请求拦截器request参数有config和error
- 请求拦截器request的config可以配置请求头和令牌
- 先配置响应拦截器配合弹窗message过滤不需要的return空;留下需要的res.data,再完成表单登录提交,获得token后配合vuex或者localstorge配置请求拦截器添加token!优先使用localstorage
- 坑:
--axios一定要先实例化再调用实例化的instance来进行请求,instance和axios用法一致
--axios的全局拦截器不会对axios实例生效!!!应该对实例instance单独配置拦截器
--拦截器拦截完成后一定要返回!
7.响应拦截器先判断状态码在判断code得到data和message
8 localstorage的方法:
--储存token,特点:长期存储在浏览器,必须手动删除
setitem (坑:传进去的所有数据都会变成String类型!)
getitem
removeitem (点击注销功能实现)
实例化axios初始化和引入需要的插件
import axios from 'axios'
import { Message } from 'element-ui';
import store from '../store/index'
const instance = axios.create({
baseURL: 'https://more.atcumt.com',
timeout: 5000
})
export function postrequest(param, body) {
return instance.post(param, body)
}
响应拦截器实现:
instance.interceptors.response.use(
response => {
if (response.status == 200) {
if (response.data.code == '200') {
console.log('44');
console.log(response.data.data.token);
if (response.data.data.token) {
window.localStorage.setItem('token', response.data.data.token)
}
Message.success('成功')
return response.data
}
if (response.data.code == '1002') {
Message.error('用户不存在')
return;
} if (response.data.code == '1003') {
Message.error('密码错误')
return;
}
//register code
console.log(response.data);
if (response.data.code == '1001') {
Message('用户已存在')
return;
}
if (response.data.code == '1004') {
Message('学号或密码格式错误')
return;
}
}
},
error => {
console.log(error);
}
)
请求拦截器实现:
功能:使用localstorage和vuex混合储存并携带token --以后研究一下vuex持久化QWQ
instance.interceptors.request.use(
config => {
if (window.localStorage.getItem('token')) {
store.state.token = window.localStorage.getItem('token');
}
if (store.state.token) {
window.localStorage.setItem('token', store.state.token)
config.headers.Authorization = store.state.token
}
return config
}
)
2. element ui中form实现登录注册和button
element ui中form组件的使用及api(表单验证rule、v-model绑定表单...)--多看文档!真香!这里就不细说了
表单提交用自带的methods--submitform+对应的表单ref 在提交成功处添加获取数据的请求
这里多次使用v-if是因为有个bug暂未解决------
1月10日,将控制dom的display改为v-if条件渲染
小问题:分别指定了key,第二次渲染出表单时,input里面的内容却还在(表单复用?),分别添加key也无效
//------------------------------------------------
//登录表单
<div class="login" @keydown="enter($event, 'loginform', 'registerform')">
<el-form
ref="loginform"
:model="ruleForm"
:rules="rules"
label-width="80px"
v-loading="loading"
v-if="islogin"
key="login_form"
>
<h1>系统登录</h1>
<el-form-item label="用户名" prop="username">
<el-input
v-model="ruleForm.username"
placeholder="请输入用户名"
v-if="islogin"
key="login_name"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
placeholder="请输入密码"
v-model="ruleForm.password"
show-password
v-if="islogin"
key="login_password"
></el-input>
</el-form-item>
</el-form>
//------------------------------------------------------------
//注册表单
<el-form
ref="registerform"
:model="ruleForm_r"
:rules="rules_r"
label-width="80px"
v-loading="loading"
v-if="!islogin"
key="register_form"
>
<h1>账号注册</h1>
<el-form-item label="用户名" prop="username_r">
<el-input
v-model="ruleForm_r.username_r"
placeholder="请输入您的学号"
v-if="!islogin"
key="register_name"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="password_r">
<el-input
placeholder="请自定义密码"
v-model="ruleForm_r.password_r"
show-password
v-if="!islogin"
key="register_password"
></el-input>
</el-form-item>
</el-form>
//------------------------------------------------
//login和register按钮
<el-button
size="medium"
@click="submitloginForm('loginform')"
:class="{ loginbtn: islogin, registerbtn: !islogin }"
>登录</el-button
>
<el-button
size="medium"
@click="submitregisteForm('registerform')"
:class="{ loginbtn: !islogin, registerbtn: islogin }"
>注册</el-button
>
//------------------------------------------------
</div>
配置项:
登录注册按钮表单切换和使用:
判断当前currenttype再选择 切换表单 or 执行相应功能
//-----------------------------------------------------------------
data() {
return {
islogin: true, //islogin用于v-if动态切换表单类名,完成过渡动画
loading: false,
currenttpye: "login"
}
}
// -----------------------------------------------------------
//loginForm
submitloginForm(loginform) {
if (this.currenttpye == "register") {
this.islogin = !this.islogin;
this.$refs.registerform.$el.style.display = "none";
this.$refs.loginform.$el.style.display = "block";
this.currenttpye = "login";
} else {
this.$refs[loginform].validate((valid) => {
if (valid) {
this.loading = true;
postrequest("/user/login", {
studentId: this.ruleForm.username, //学号
password: this.ruleForm.password, //密码
}).then((res) => {
this.loading = false;
if (res.data.token) {
this.$store.state.token = res.data.token;
this.$router.replace("/Home");
}
});
} else {
console.log("error submit!!");
return false;
}
});
}
},
//registerForm
submitregisteForm(registerform) {
if (this.currenttpye == "login") {
this.islogin = !this.islogin;
this.$refs.registerform.$el.style.display = "block";
this.$refs.loginform.$el.style.display = "none";
this.currenttpye = "regsiter";
console.log(this.currenttpye);
} else {
console.log(this.$refs[registerform]);
this.$refs[registerform].validate((valid) => {
if (valid) {
this.loading = true;
postrequest("/user/register", {
studentId: this.ruleForm_r.username_r, //学号
password: this.ruleForm_r.password_r, //密码
}).then((res) => {
this.loading = false;
console.log(res.data.token);
if (res.data.token) {
//注册完成之后切换表单
this.islogin = !this.islogin;
this.currenttpye='login'
this.$refs.registerform.$el.style.display = "none";
this.$refs.loginform.$el.style.display = "block";
}
});
} else {
console.log("re error submit!!");
return false;
}
});
}
},
enter回车键提交表单的功能:
<div class="login" @keydown="enter($event, 'loginform', 'registerform')">
----------------------------------------------
enter(e, loginform, registerform) {
console.log(e);
if (e.key == "Enter") {
if (this.currenttpye == "login") {
this.submitloginForm(loginform);
} else if (this.currenttpye == "register") {
this.submitregisteForm(registerform);
}
}
},
3. vue-router完善登录页面功能
全局路由守beforeEach(to,from,next)钩子的使用:
实现的功能:无token无法强制更改url进入主页面
-
大坑:函数全局路由守卫一定要放在vue实例对象之前,我是伞兵QWQ
-
报错:无next()函数--用错钩子,用成afterEach钩子了
-
next(option) 传进去参数path可以改变路径,不传任何参数会继续执行当前路由跳转操作
-
返回登录页面时无限跳转bug问题:加入
else if (!window.localStorage.getItem('token')&&to.path == '/login') {
next();
}
用来判断:如果没有token则返回登录页面后就无需再次判断是否拥有token的bug
router.beforeEach((to, from, next) => {
if (window.localStorage.getItem('token') ) {
next()
}
else if (!window.localStorage.getItem('token')&&to.path == '/login') {
next();
}
else {
next({
path: '/login',
})
}
})
...
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
注销功能的实现核心:
点击清空token并且replace到login组件
this.window.localStorage.removeItem('token')
this.$router.replace('login')
--今天刚考完高数嘿嘿熬夜敲代码,加油洋仔!
--努力努力再努力