1.开发流程总览:
1.首先是对样式进行了修改 【登录页】
2.表单校验-这一环节中使用了element提供的el-form表单校验 ,对手机号和密码进行了校验。
3.封装登录的接口。【单独的文件,导出使用】逻辑是:如果用户输入的通过校验,则点击登录的时候发起请求。可在组件中导入,然后执行,也可使用actions,效果一样,但因为token要保存在vuex中,所以使用vuex方法保存
4.优化-响应拦截器,目的是:获取数据方便,另一个目的是如果出现错误,没有错误提示。而经过响应拦截器,可以把错误抛给catch(在actions里),取数据也更简单
5.优化-使用环境变量进行端口配置。目的:开发和上线的基地址不一样,他可以自动的切换,方便。
6.优化-解决跨域问题。我用的本地服务器接口,我的端口是3000,和请求的地址不一样,很明显跨域了。我使用的是脚手架提供的代理服务器,只需要修改一点配置项就行了
具体点的逻辑是:假设目标端口(假设就端口不一样)是8001,而我的端口是3000.那么在proxy(脚手架配置项要写真实的端口号)而我们的基地址一定不能固定的地址,不然打包后就打不开了。在baseURL中写环境变量
7.将token保存到vuex中,目的是为了获得权限访问页面。在actions中发的请求,所以保存的逻辑应该也在actions里面
8.优化-在请求拦截器里注入token,目的是如果访问某些需要权限的页面,带上的话就可以访问,也就是从vuex中取出来,再填充到header中。config.headers['Authorization'] = `Bearer ${token}`这是固定格式--这样不用每次手动加token发起请求
9.优化-token持久化,目的:让token的保存时间边长,不至于一刷新页面就要重新登录。二次开发已经提供了,只需要在vuex中处理逻辑(看你在哪里发请求了)
10.点击登录后,重点是点击登录应该是输入通过校验后,才发起请求。跳转使用编程式跳转push()。使用的是路由守卫,页面跳转时进入前置路由守卫,目的是进行跳转限制,一个是已经登录的不能再登录,在一个是没登录的不能访问除登录页之外的,在前置路由这里做逻辑。(因为项目是后台管理,不存在首页让你无权限浏览)
11.加了一点样式,跳转的进度条,一个小插件,NProgress
12.然后是修改主页的样式
13.封装api获取用户资料,重点是一定要在进入首页之前拿到用户个人资料,因为这是后台管理系统,每个人的权限不同,看到的页面也是不一样的,你等人家过来了再发请求不合适,来不及。所以这个业务逻辑应该在路由守卫里做,当然在login也行,不过不如在路由守卫里做,因为他是专业的路由跳转的,且login登录不一定去哪里呢,万一地址栏一通乱输。主要逻辑是:首先token已经存在且成功获取数据之后才能进项跳转
14.这里的头像获取需要取出用户的id,再用用户id去获取用户个人头像,然后头像保存在vuex中
14.然后进行数据渲染
2.响应拦截器
2.1使用原因:
- 获取ajax的返回结果比较麻烦:res.data.data.XXXX(拿数据更方便一些)
- 登录时,填写错误的用户名密码,没有错误提示(没有进入catch分支,使用它抛出错误)
2.2 作用一:
在响应拦截器中,根据本次请求返回的数据中的success字段值,来决定是否主动抛出错误。
// 响应拦截器 service.interceptors.response.use(response => { if (response.data.success) { // 操作成功 } else { // 如果success为false 业务出错,直接触发reject // 被catch分支捕获 return Promise.reject(new Error(message)) } }, error => { return Promise.reject(error) // 返回执行错误 让当前的执行链跳出成功 直接进入 catch })
注:success是和后端约定好的,如果请求成功就返回一个success。如果失败会把错误返回给catch
2.3 作用二: 解决获取有效数据代码冗余的问题
观察api的返回结果,我们发现axios在处理接口返回值时,默认会自动给包裹一个data字段,这导致我们每次在业务模块获取数据都需要写res.data.data.xxxx。
目的:在返回有效数据时,直接返回res.data
// 响应拦截器 service.interceptors.response.use(response => { if (response.data.success) { // 操作成功 + return response.data } else { // 如果success为false 业务出错,直接触发reject // 被catch分支捕获 return Promise.reject(new Error(message)) } }, error => { return Promise.reject(error) // 返回执行错误 让当前的执行链跳出成功 直接进入 catch })
2.4 总结:
- 响应拦截器用来处理后端接口返回的数据---脱壳处理。
- 判断某个操作是否成功,需要根据后端接口返回值中某个特殊字段(一般是由后端同学来约定)来判断,而不能只是依靠axios内置的报错机制
3.环境变量
在.env.development 和 .env.production 中分别写基地址
3.1 作用:环境变量在不同的环境下(开发环境、生产环境)可以变换的变量(典型应用就是可以做基地址切换,是自动 的)因为项目开发用的基地址1 ,上线之后肯定需要换另一个基地址2,所以就用到了环境变量。
因为不用他只能用手写了,不方便。
3.2.配置
.env.devlopment
例如: # 开发环境的基础地址 VUE_APP_BASE_API = 'http://ihrm-java.itheima.net/api'
.env.production
1. # 生产环境的基地址 2. VUE_APP_BASE_API = 'http://www.xxx.com/prod-api'
3 .3 总结:设置环境变量,我们可以在不同的环境下使用不同axios基地址
4.跨域解决---跨域-Vue-Cli配置代理转发
4.1 思路:
在前端服务和后端接口服务之间 架设一个中间代理服务,它的地址保持和前端服务一致,那么:
中间服务和前端服务之间由于协议域名端口三者统一不存在跨域问题,可以直接发送请求
中间服务和后端服务之间由于并不经过浏览器没有同源策略的限制,可以直接发送请求
这样,我们就可以通过中间这台服务器做接口转发,在开发环境下解决跨域问题,看起来好像挺复杂,其实vue-cli已经为我们内置了该技术,我们只需要按照要求配置一下即可。
4.2 配置说明:在vue.config.js
配置文件中,有一项是devServer,它就是我们下边要操作的主角。
module.exports = { devServer: { // ... 省略 // 代理配置 proxy: { // 如果请求地址以/api打头,就出触发代理机制 // http://localhost:9588/api/login -> http://localhost:3000/api/login '/api': { target: 'http://localhost:3000' // 我们要代理的真实接口地址 } } } } }
4.3 基地址
.env.development
VUE_APP_BASE_API = '/api'
api/user.js
export function login(formData) { return request({ / url: 'api/sys/login', + url: '/sys/login', // 前面的api就省略了 method: 'POST', data: formData }) }
4.4 最后:一定要重启项目(因为修改了配置文件)
ajax的基地址baseUrl必须是相对地址,而不能是绝对地址
4.5 总结:
vue-cli集成了跨域代理功能-- 只能用在开发阶段。
vue.config.js文件中,在devServe下按指定格式配置了proxy,再重启项目即可。
5 .token处理
5.1 token作为我们其它请求的用户标识,我们使用请求拦截器做一下统一处理,让每一个请求的header中都拥有token
5.2 使用 :在请求拦截器中注入token:
1.引入store
2.代码逻辑:如果当前vuex中有token,就在请求头中设置上。
import store from '@/store' service.interceptors.request.use( config => { const token = store.state.user.token // 如果当前存有token,就加在请求头上 if (token) { config.headers['Authorization'] = `Bearer ${token}` } return config } , error => { return Promise.reject(error) })
上面的authorization和bearer 是本项目的后端接口要求的写法。
5.3 总结:
- 在普通js文件中使用store时,直接导入模块即可
- 所有的请求都会经过请求拦截器,所以方便它用来统一给请求头中添加token
6 .token持久化
现在的token是保存在vuex中,而页面刷新之后,vuex的内容丢失了,将会导致接口访问异常。所以我们需要对token做持久化处理: 刷新页面之后token不丢失。
6.1 思路
- 在对token进行初始化的时候先从本地取一下,优先使用本地取到的值
- 在设置token的时候除了在vuex中存一份,在本地也同步存一份
- 在删除token的时候除了把vuex中的删除掉,把本地的也一并删除
6.2 使用: 1.由于是二次开发,已经为我们提供了,可以直接使用
import Cookies from 'js-cookie' const TokenKey = 'hrsaas-ihrm-token' // 设定一个独一无二的key export function getToken() { return Cookies.get(TokenKey) } export function setToken(token) { return Cookies.set(TokenKey, token) } export function removeToken() { return Cookies.remove(TokenKey) }
2.在vuex中引入方法,并调用
3.actions、mutations、state使用
7 今日小知识:
1.修改了配置文件需要重启项目
2.数据库第一次运行用 npm run start --之后就可以用npm run serve
3.postman没有跨域错误
4.可以下一个cors插件解决浏览器同源策略实现跨域
5.vue脚手架解决跨域-如果请求地址以XXX打头就触发代理,如果直接请求目标地址了 ,那就走不了代理自然还是跨域(所以基地址还是要设置成跨域前的基地址,)重要:脚手架配置项写真实要请求的地址
6. .env.dev配置文件要改,改成跨域前的地址不一样(也是因为不一样才跨域),其实基础路径比较灵活且固定,不要太拘泥
7.脚手架跨域代理只能在开发阶段用
8.koa(插件)--后端解决cors问题(后端允许前段跨域)
9.如何在.js中获取vuex的数据 ---import store from XX(导入即可) 然后 store.XX
10.拿回来的数据要保存在vuex中在action中使用比较好。如果在组件中使用的话,直接在组件发请求就好。
11.this.$store.dispatch()也是异步的,如果想实现同步的效果,前面加await
12.命名空间的名字要在store的modules中看。
13.代理服务器和客户端是同源的,道理很简单,你不和他同源岂不又是跨域
14.点击登录跳转一定要是异步的。不然你点登陆了,ajax还不知道在哪呢
15.dispatch 是异步的
16.includes(to.path)是否包含某个路径(数组中有没有值在里面)includes.数组名是个方法
17..js文件拿命名空间里的state里的数据——store.state.user.token--看清楚,state在命名空间名的前面--注意格式不要错
18.SVG格式的图片 待学习
19.拿个人信息在进入主页之前,在路由守卫中去做,因为进入首页后会根据不同的token权限,展示不同的页面,所以一定要在进入主页之前去做,不然就晚了。在login去做也凑合,但不能保证一定从login登录,路由守卫的作用就是,只要有路由跳转,就起作用。
20.刷新页面路由守卫也会执行
21.actions里面可以写很多个请求。
22.防抖和节流的英文 待学习
23.NProgress.start() 启动进度条 还有个done()
24数组.includes(to.path) ---注意格式