持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情
接CMS数据可视化01
配置Axios项目根路径
-
目前echarts图表中的数据都是假数据
-
如果获取真数据就需要调用接口
-
这就需要至少要完成注册、登录、初始化数据等接口的调用才行
-
项目中接口根路径是相同的,见前文 重要的三个地址
-
所以,在
assets/utils文件夹,创建axios的配置文件,取名common.js。代码如下:axios.defaults.baseURL = 'http://www.itcbc.com:8000';这里之所以放到 assets/utils 文件夹中,是因为 utils 在编程中常用来放工具函数。而request是请求的意思。
注册账号
切换登录和注册的盒子
登录和注册同在 login.html 中,因为定位的原因重叠在一起了。我们可以通过JS实现切换两个盒子
// 切换两个盒子
document.querySelector('.login a').addEventLister('click', function () {
document.querySelector('.login').style.display = 'none';
document.querySelector('.register').style.display = 'block';
})
document.querySelector('.register a').addEventLister('click', function () {
document.querySelector('.login').style.display = 'block';
document.querySelector('.register').style.display = 'none';
})
表单验证
- 略
完成注册
当表单验证通过后,根据接口文档,获取输入框的账号和密码,Ajax提交账号和密码
document.querySelector('.register form').addEventListener('submit', function (e) {
e.preventDefault();
// 通过验证,这里的代码将会执行。我们将Ajax请求的代码放到这里即可
let data = $(this).serialize();
// console.log(data);
axios.post('/api/register', data).then(({ data: res }) => {
// console.log(res);
if (res.code === 0) { // 我们只考虑成功的情况即可,失败的情况后续统一使用拦截器处理
toastr.success(res.message); // 使用插件提示消息
document.querySelector('.register input').value = ''; // 清空输入框
document.querySelector('.register a').click(); // 切换至登录的盒子
}
})
});
登录功能
-
因为前文已经完成了注册,所以这里的登录功能极为简单
-
问题是,登录如果成功,该做什么?
- 将服务器响应的token存储到本地存储(关于token的说明见下文的 JWT身份认证)
- 跳转到 index.html 页面 (页面跳转,只考虑两个html之间的相对关系,不考虑js在哪里)
登录的代码如下:
document.querySelector('.login form').addEventListener('submit', function (e) {
e.preventDefault();
//提交逻辑
let data = $(this).serialize();
// console.log(data);
axios.post('/api/login', data).then(({ data: res }) => {
// console.log(res);
if (res.code === 0) {
localStorage.setItem('token', res.token);
location.href = './index.html'
}
})
});
JWT身份认证
什么是jwt身份认证
在前后端分离模式的开发中,服务器如何知道来访者的身份呢?
- 在登录后,服务器会响应给用户一个 令牌 (token)
- 令牌中会包括该用户的id等唯一标识
- 浏览器收到令牌后,自己保存
- 下次请求其他接口时,(在请求头中)携带这个令牌去请求
- 这样服务器就知道来访者的身份了,服务器就会为该用户开发接口的访问权限,并处理该用户的数据
这样,就明白为什么登录后,要将token保存到本地存储中了。
全局配置请求头
由于除了登录和注册接口外,其他所有接口都需要身份认证(都需要我们提供令牌),所以我们可以在 request.js 中,全局配置请求头。
axios.defaults.headers.common['Authorization'] = localStorage.getItem('token');
利用令牌控制页面的访问权限
浏览器端,可以通过合理使用令牌,控制页面的访问权限。
比如,用户默认只能访问登录页,如果不登录就不能访问首页,怎么做?
第一个判断:判断本地存储是否有token
<!-- index.html -->
<!-- 本地存储有token,则说明用户登录了;没有token,则说明用户没有登录,不允许访问首页 -->
<script>
if (localStorage.getItem('token') === null) location.href = './login.html'
</script>
上述判断只能判断token有没有,但不能判断token的真假,所以需要发送Ajax请求,根据服务器响应结果再次判断
第二个判断:根据服务器响应结果,判断token是否是假token或者过期的token
- 如果token值是正确的,是没有过期的,则服务器响应
code===0 - 如果token是错误的获取过期的,则服务器响应
code===1 && message==='身份认证失败'
// request.js 中,使用响应拦截器,拦截响应结果进行判断
// 如果响应结果中 code === 1 && message === '身份认证失败' 则表示浏览器使用了无效的token
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
if (error.response) {
if (error.response.data.message === '身份认证失败') {
localStorage.removeItem('token');
location.href = './login.html'
}
}
return Promise.reject(error);
});
统一处理错误提示
在上述响应拦截器的基础之上,顺便添加响应错误提示。
所有接口响应的结果有两种:
- 响应状态码 小于 400,并且
code===1,比如登录账号密码错误。这样的响应进入响应拦截器中的第一个函数。 - 响应状态码 大于等于 400,并且
code === 1,比如身份认证失败。这样的响应进入响应拦截器中的第二个函数。
所以分别提示
// request.js 中,使用响应拦截器,拦截响应结果进行判断
// 如果响应结果中 code === 1 && message === '身份认证失败' 则表示浏览器使用了无效的token
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
if (response.data.code === 1) {
toastr.warning(response.data.message)
}
return response;
}, function (error) {
// 对响应错误做点什么
if (error.response) {
if (error.response.data.message === '身份认证失败') {
localStorage.removeItem('token');
location.href = './login.html'
} else {
toastr.error(error.response.data.message);
}
}
return Promise.reject(error);
});
退出登录
一般来说,退出需要做的事和登录后做的事刚好相反。
- 登录后,在本地存储了token;退出时,移除这个token
- 登录后,跳转到了 index.html 页面;退出时,跳转到 login.html
// ------------------------ 退出登录 -------------------
document.querySelector('.logout a').addEventLister('click', function () {
if (!confirm('确定要退出登录吗?')) return;
localStorage.removeItem('token');
location.href = './login.html';
})
初始化数据
为了减少手动录入数据的时间,特别设计了此接口。调用此接口将为你随机添加56名同学,并分为8个组。并为每位同学随机添加了三次成绩。
// ------------------------ 初始化数据 -------------------
document.querySelector('.init').addEventLister('click', function () {
axios.get('/init/data').then(({ data: res }) => {
if (res.code === 0) {
toastr.success(res.message);
}
})
})
班级概况
- 查阅接口文档,发现服务器已经将数据计算整理完毕,提供了现成的接口。
- 所以我们前端开发者,只需要调用接口,并将数据展示到页面中即可。
// 获取班级概况数据
axios.get('/student/overview').then(({ data: res }) => {
// console.log(res);
let { code, data } = res;
if (code === 0) {
document.querySelector('.overview .total').innerHTML = data.total;
document.querySelector('.overview .avgAge').innerHTML = data.avgAge;
document.querySelector('.overview .avgSalary').innerHTML = data.avgSalary;
document.querySelector('.overview .proportion').innerHTML = data.proportion;
}
})
最后是原图