前面写的了解了一下vue这个框架,所有的框架都要在实际应用里感受一下好坏.
这里用vue+vuex+Ts+elementEI来做一个项目
git地址:
https://github.com/544076724/...
首先下载vue-cli 这里用的版本是4.5.9
首先创建项目
vue create edu-boss-fed
然后来回答一些问题
这里我们自己配置要的选项
然后第一个不选默认是2.0版本的vue,这里我们用2.0。
然后把babel,ts,router,vuex,css预处理器,和lint都选上.
然后勾选ts之后,我们把使用类样式的组件语法 也勾选上(可以写jsx语法了)
这个也是yes,我们让ts只处理类型注解,然后语法的转换还是交给babel来处理(ts处理不够完善).
这里我们选的no,我们这个项目用hash模式路由,如果后期需要history模式再配置.
这里用第一个,最新的sass
这里我们用Standard规则,这个规则相对比较松,比较适合个人或小团队使用.
这里我们都勾选上,保存save和commit提交时都对代码进行修复.
然后第一个,把eslint以及其他配置都用单独文件配置.
最后看个人需要,是否要储存我们之前选择的这一套来生成个模板,方便下次使用.
这个代码里主要有个需要关注的地方是在请求的封装,拦截器这里
贴一下代码
// 请求拦截器
request.interceptors.request.use(function (config) {
// 我们就在这里通过改写 config 配置信息来实现业务功能的统一处理
const { user } = store.state
if (user && user.access_token) {
config.headers.Authorization = user.access_token
}
// 注意:这里一定要返回 config,否则请求就发不出去了
return config
}, function (error) {
// Do something with request error
return Promise.reject(error)
})
// 响应拦截器
let isRfreshing = false // 控制刷新 token 的状态
let requests: any[] = [] // 存储刷新 token 期间过来的 401 请求
request.interceptors.response.use(function (response) { // 状态码为 2xx 都会进入这里
// console.log('请求响应成功了 => ', response)
// 如果是自定义错误状态码,错误处理就写到这里
return response
}, async function (error) { // 超出 2xx 状态码都都执行这里
// console.log('请求响应失败了 => ', error)
// 如果是使用的 HTTP 状态码,错误处理就写到这里
// console.dir(error)
if (error.response) { // 请求发出去收到响应了,但是状态码超出了 2xx 范围
const { status } = error.response
if (status === 400) {
Message.error('请求参数错误')
} else if (status === 401) {
// token 无效(没有提供 token、token 是无效的、token 过期了)
// 如果有 refresh_token 则尝试使用 refresh_token 获取新的 access_token
if (!store.state.user) {
redirectLogin()
return Promise.reject(error)
}
// 刷新 token
if (!isRfreshing) {
isRfreshing = true // 开启刷新状态
// 尝试刷新获取新的 token
return refreshToken().then(res => {
if (!res.data.success) {
throw new Error('刷新 Token 失败')
}
// 刷新 token 成功了
store.commit('setUser', res.data.content)
// 把 requests 队列中的请求重新发出去
requests.forEach(cb => cb())
// 重置 requests 数组
requests = []
return request(error.config)
}).catch(err => {
console.log(err)
Message.warning('登录已过期,请重新登录')
store.commit('setUser', null)
redirectLogin()
return Promise.reject(error)
}).finally(() => {
isRfreshing = false // 重置刷新状态
})
}
// 刷新状态下,把请求挂起放到 requests 数组中
return new Promise(resolve => {
requests.push(() => {
resolve(request(error.config))
})
})
} else if (status === 403) {
Message.error('没有权限,请联系管理员')
} else if (status === 404) {
Message.error('请求资源不存在')
} else if (status >= 500) {
Message.error('服务端错误,请联系管理员')
}
} else if (error.request) { // 请求发出去没有收到响应
Message.error('请求超时,请刷新重试')
} else { // 在设置请求时发生了一些事情,触发了一个错误
Message.error(`请求失败:${error.message}`)
}
// 把请求失败的错误对象继续抛出,扔给上一个调用者
return Promise.reject(error)
})
在这里我们的 token 无效(没有提供 token、token 是无效的、token 过期了)的话,会尝试刷新token然后再次发送之前失败的请求.
token过期时间比较短(为了安全), 刷新token接口(还失败就让重新登陆)只能执行一次
这里的实现是 刷新 token状态时,把 其他请求都储存起来并 返回 promise 等待未来 刷新成功后 重新请求 并且请求结果 返回 决议 promise状态
这是 实现。上面是简化版本
let r;
let p = new Promise(resolve => {
r = resolve //储存决议函数
})
requests.push({
r,config:error.config //储存决议函数和对应请求配置,方便后续调用
})
requests.forEach(item => item.r(request(item.config)));
其他的就是一些常见的需求,有兴趣可以下载下来跑跑看
登陆账号:18201288771
密码:111111
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。