vue-axios-optimize 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +484 -476
- package/index.js +1 -1
- package/package.json +17 -17
package/README.md
CHANGED
|
@@ -1,477 +1,485 @@
|
|
|
1
|
-
# vue-axios-optimize使用说明
|
|
2
|
-
|
|
3
|
-
vue-axios-optimize是一个对axios请求优化的vue插件包,引入此包之后,并进行相关配置,即可轻松实现全局请求加载动画,重复请求时取消前面的请求或者阻止后面的请求。
|
|
4
|
-
|
|
5
|
-
## 安装
|
|
6
|
-
|
|
7
|
-
```shell
|
|
8
|
-
npm install vue-axios-optimize
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
## 引入
|
|
12
|
-
|
|
13
|
-
在src/api目录下新建axios-optimize.js文件
|
|
14
|
-
|
|
15
|
-
api目录大致如下
|
|
16
|
-
|
|
17
|
-
> src
|
|
18
|
-
>
|
|
19
|
-
> > api
|
|
20
|
-
> >
|
|
21
|
-
> > > modules
|
|
22
|
-
> > >
|
|
23
|
-
> > > > common-api.js
|
|
24
|
-
> > >
|
|
25
|
-
> > > index.js
|
|
26
|
-
> > >
|
|
27
|
-
> > > axios.js
|
|
28
|
-
> > >
|
|
29
|
-
> > > axios-optimize.js
|
|
30
|
-
|
|
31
|
-
axios-optimize.js文件内容大致如下
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
import axios from 'axios'
|
|
35
|
-
import instance from '@/api/axios.js'
|
|
36
|
-
|
|
37
|
-
import axiosOptimize from 'vue-axios-optimize'
|
|
38
|
-
import { useAppStoreHook } from '@/store/modules/app'
|
|
39
|
-
const useAppStore = useAppStoreHook()
|
|
40
|
-
|
|
41
|
-
import { useUserStoreHook } from '@/store/modules/user'
|
|
42
|
-
|
|
43
|
-
import { ElMessageBox } from 'element-plus'
|
|
44
|
-
|
|
45
|
-
const AxiosOptimize = new axiosOptimize(axios, instance, {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
config.headers
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
axios.js的内容需要做些细微的更改 大致内容如下
|
|
119
|
-
|
|
120
|
-
```js
|
|
121
|
-
import axios from 'axios'
|
|
122
|
-
import { ElMessage } from 'element-plus'
|
|
123
|
-
import { useUserStoreHook } from '@/store/modules/user'
|
|
124
|
-
|
|
125
|
-
// 创建axios实例
|
|
126
|
-
const service = axios.create({
|
|
127
|
-
baseURL: '/proxy',
|
|
128
|
-
timeout: 10000
|
|
129
|
-
})
|
|
130
|
-
|
|
131
|
-
// request拦截器
|
|
132
|
-
service.interceptors.request.use(
|
|
133
|
-
(config) => {
|
|
134
|
-
// 一般会请求拦截里面加token
|
|
135
|
-
const useUserStore = useUserStoreHook()
|
|
136
|
-
const accessToken = useUserStore.gettersAccessToken
|
|
137
|
-
if (accessToken) {
|
|
138
|
-
config.headers['authorization'] = 'Bearer ' + accessToken
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return config
|
|
142
|
-
},
|
|
143
|
-
(error) => {
|
|
144
|
-
// 这个return 一定记得 带上 否则无法使用
|
|
145
|
-
return Promise.reject(error)
|
|
146
|
-
}
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
// respone拦截器
|
|
150
|
-
service.interceptors.response.use(
|
|
151
|
-
async (res) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
|
307
|
-
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
|
315
|
-
|
|
|
316
|
-
|
|
|
317
|
-
|
|
|
318
|
-
|
|
|
319
|
-
|
|
|
320
|
-
|
|
|
321
|
-
|
|
|
322
|
-
|
|
|
323
|
-
|
|
|
324
|
-
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
import {
|
|
334
|
-
import {
|
|
335
|
-
import {
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
this.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
.
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
})
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
[
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
[vue2-
|
|
464
|
-
|
|
465
|
-
[vue3-
|
|
466
|
-
|
|
467
|
-
[vue2-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
### 1.0.
|
|
476
|
-
|
|
1
|
+
# vue-axios-optimize使用说明
|
|
2
|
+
|
|
3
|
+
vue-axios-optimize是一个对axios请求优化的vue插件包,引入此包之后,并进行相关配置,即可轻松实现全局请求加载动画,重复请求时取消前面的请求或者阻止后面的请求。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
```shell
|
|
8
|
+
npm install vue-axios-optimize
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## 引入
|
|
12
|
+
|
|
13
|
+
在src/api目录下新建axios-optimize.js文件
|
|
14
|
+
|
|
15
|
+
api目录大致如下
|
|
16
|
+
|
|
17
|
+
> src
|
|
18
|
+
>
|
|
19
|
+
> > api
|
|
20
|
+
> >
|
|
21
|
+
> > > modules
|
|
22
|
+
> > >
|
|
23
|
+
> > > > common-api.js
|
|
24
|
+
> > >
|
|
25
|
+
> > > index.js
|
|
26
|
+
> > >
|
|
27
|
+
> > > axios.js
|
|
28
|
+
> > >
|
|
29
|
+
> > > axios-optimize.js
|
|
30
|
+
|
|
31
|
+
axios-optimize.js文件内容大致如下
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import axios from 'axios'
|
|
35
|
+
import instance from '@/api/axios.js'
|
|
36
|
+
|
|
37
|
+
import axiosOptimize from 'vue-axios-optimize'
|
|
38
|
+
import { useAppStoreHook } from '@/store/modules/app'
|
|
39
|
+
const useAppStore = useAppStoreHook()
|
|
40
|
+
|
|
41
|
+
import { useUserStoreHook } from '@/store/modules/user'
|
|
42
|
+
|
|
43
|
+
import { ElMessageBox } from 'element-plus'
|
|
44
|
+
|
|
45
|
+
const AxiosOptimize = new axiosOptimize(axios, instance, {
|
|
46
|
+
responseTypesStr: "arraybuffer,blob",
|
|
47
|
+
showLoadingFun: () => {
|
|
48
|
+
// 展示加载动画方法
|
|
49
|
+
useAppStore.setLoadingStatus(true)
|
|
50
|
+
},
|
|
51
|
+
hideLoadingFun: () => {
|
|
52
|
+
// 关闭加载动画方法
|
|
53
|
+
useAppStore.setLoadingStatus(false)
|
|
54
|
+
},
|
|
55
|
+
openRefresh: true, // 开启无感知刷新token 默认不开 开启时 下面的参数才有效
|
|
56
|
+
refreshApiUrl: '/xiaobu-admin/refresh-token', // 刷新tokenApi的 url
|
|
57
|
+
getRefreshTokenFun: () => {
|
|
58
|
+
const useUserStore = useUserStoreHook()
|
|
59
|
+
// 获取refreshToken
|
|
60
|
+
return useUserStore.gettersRefreshToken
|
|
61
|
+
},
|
|
62
|
+
reloginFun: async (response) => {
|
|
63
|
+
// 重新登录方法 建议如下形式清除 缓存中token等信息后 弹框提示 点击确认后 刷新页面
|
|
64
|
+
const useUserStore = useUserStoreHook()
|
|
65
|
+
// 清除缓存中的token等信息
|
|
66
|
+
await useUserStore.clearAuth()
|
|
67
|
+
ElMessageBox.alert(`${response.message}`, '提示', {
|
|
68
|
+
confirmButtonText: 'OK',
|
|
69
|
+
showClose: false,
|
|
70
|
+
callback: async (action) => {
|
|
71
|
+
if (action === 'confirm') {
|
|
72
|
+
// 刷新浏览器是为了 跳转登录页时query的redirect 会带上 当前页面地址(路由拦截处的逻辑)
|
|
73
|
+
window.location.reload()
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
},
|
|
78
|
+
refreshTokenStore: (refreshToken) => {
|
|
79
|
+
// 使用refreshToken 调用刷新token接口 获取新的accessToken 并存储到对应缓存中 使接口能用
|
|
80
|
+
const useUserStore = useUserStoreHook()
|
|
81
|
+
// 调用store的获取refreshToken方法 同时会将新的accessToken存储到缓存
|
|
82
|
+
return useUserStore.refreshTokenAction({ refreshToken })
|
|
83
|
+
},
|
|
84
|
+
setAccessTokenFun: (config, accessToken) => {
|
|
85
|
+
// 根据需求给请求头设置 accessToken 如下两种形式可设置请求头 二选一
|
|
86
|
+
// Reflect.set(config.headers, 'authorization', 'Bearer ' + accessToken)
|
|
87
|
+
config.headers.authorization = 'Bearer ' + accessToken
|
|
88
|
+
},
|
|
89
|
+
responseResultFun: (res) => {
|
|
90
|
+
/*res数据结构大致如下: 为接口返回的最外层数据 加个 请求时的config
|
|
91
|
+
{
|
|
92
|
+
code: 200,
|
|
93
|
+
data: XXX,
|
|
94
|
+
message: XXX,
|
|
95
|
+
config: {}
|
|
96
|
+
}
|
|
97
|
+
*/
|
|
98
|
+
// 此方法配置 返回数据 的 逻辑
|
|
99
|
+
if (res.config.responesType === 'blob') {
|
|
100
|
+
delete res.config
|
|
101
|
+
return res
|
|
102
|
+
}
|
|
103
|
+
if (res.code === 200) {
|
|
104
|
+
return res.data
|
|
105
|
+
}
|
|
106
|
+
delete res.config
|
|
107
|
+
return res
|
|
108
|
+
},
|
|
109
|
+
formatAccessToken: (data) => {
|
|
110
|
+
// 此方法返回 请求接口后 返回的 accessToken
|
|
111
|
+
return data.accessToken
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
export default AxiosOptimize.instance
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
axios.js的内容需要做些细微的更改 大致内容如下
|
|
119
|
+
|
|
120
|
+
```js
|
|
121
|
+
import axios from 'axios'
|
|
122
|
+
import { ElMessage } from 'element-plus'
|
|
123
|
+
import { useUserStoreHook } from '@/store/modules/user'
|
|
124
|
+
|
|
125
|
+
// 创建axios实例
|
|
126
|
+
const service = axios.create({
|
|
127
|
+
baseURL: '/proxy',
|
|
128
|
+
timeout: 10000
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// request拦截器
|
|
132
|
+
service.interceptors.request.use(
|
|
133
|
+
(config) => {
|
|
134
|
+
// 一般会请求拦截里面加token
|
|
135
|
+
const useUserStore = useUserStoreHook()
|
|
136
|
+
const accessToken = useUserStore.gettersAccessToken
|
|
137
|
+
if (accessToken) {
|
|
138
|
+
config.headers['authorization'] = 'Bearer ' + accessToken
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return config
|
|
142
|
+
},
|
|
143
|
+
(error) => {
|
|
144
|
+
// 这个return 一定记得 带上 否则无法使用
|
|
145
|
+
return Promise.reject(error)
|
|
146
|
+
}
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
// respone拦截器
|
|
150
|
+
service.interceptors.response.use(
|
|
151
|
+
async (res) => {
|
|
152
|
+
// 二进制数据则直接返回
|
|
153
|
+
if (res.request.responseType === "blob" || res.request.responseType === "arraybuffer"){
|
|
154
|
+
return res
|
|
155
|
+
}
|
|
156
|
+
const { config, data } = res
|
|
157
|
+
|
|
158
|
+
// code为200 直接返回有用数据 多返回一个config ...data 为接口返回的最外层数据
|
|
159
|
+
if (data.code === 200) {
|
|
160
|
+
return { ...data, config }
|
|
161
|
+
}
|
|
162
|
+
// 当项目无 无感知刷新token的功能时 此处对应code该什么逻辑就什么逻辑
|
|
163
|
+
// dosomething ... 如 code === 401 时 清除token 刷新页面等
|
|
164
|
+
|
|
165
|
+
// 报错时 多返回一个 报错标识 responseErr: true ...data 为接口返回的最外层数据
|
|
166
|
+
return { ...data, config, responseErr: true }
|
|
167
|
+
},
|
|
168
|
+
(error) => {
|
|
169
|
+
if (error.name === 'AxiosError') {
|
|
170
|
+
ElMessage({
|
|
171
|
+
showClose: true,
|
|
172
|
+
message: `${error.message},请检查网络或联系管理员!`,
|
|
173
|
+
type: 'error'
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
// 注意return 不可丢失
|
|
177
|
+
return Promise.reject(error)
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
export default service
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
接口处使用,如commo-api.js 大致如下
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
import axiosOptimize from '@/api/axios-optimize.js'
|
|
188
|
+
|
|
189
|
+
// 需要配置 请求接口时 不加载全局动画 则 配置 noShowLoading: true
|
|
190
|
+
// 需要配置 重复请求时 取消前面的请求 则 配置 preventDuplicateRequestsType: "cancel"
|
|
191
|
+
// 需要配置 重复请求时 禁用后面的请求 则 配置 preventDuplicateRequestsType: "prevent"
|
|
192
|
+
|
|
193
|
+
// get 请求demo 1
|
|
194
|
+
export function getDemo1(
|
|
195
|
+
data = {},
|
|
196
|
+
config = {
|
|
197
|
+
noShowLoading: true, // 配置不展示加载动画
|
|
198
|
+
preventDuplicateRequestsType: "cancel" // 配置重复请求时 取消前面的请求
|
|
199
|
+
}
|
|
200
|
+
) {
|
|
201
|
+
return axiosOptimize.get(`/xiaobu-admin/getDemo1`, { params: data, ...config })
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// get 请求 demo 2
|
|
205
|
+
export function getDemo2(
|
|
206
|
+
data = {},
|
|
207
|
+
config = {
|
|
208
|
+
preventDuplicateRequestsType: "prevent" // 配置重复请求时 后面的请求无效
|
|
209
|
+
}
|
|
210
|
+
) {
|
|
211
|
+
return axiosOptimize({
|
|
212
|
+
method: 'get',
|
|
213
|
+
url: `/xiaobu-admin/getDemo2`,
|
|
214
|
+
params: data,
|
|
215
|
+
...config
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// post 请求demo 1
|
|
220
|
+
export function postDemo1(data = {}, config = {}) {
|
|
221
|
+
return axiosOptimize.post('/xiaobu-admin/postDemo1', data, config)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// post 请求demo 2
|
|
225
|
+
export function postDemo2(data = {}, config: UserAxiosRequestConfig = {}) {
|
|
226
|
+
return axiosOptimize({
|
|
227
|
+
url: '/xiaobu-admin/postDemo2',
|
|
228
|
+
method: 'post',
|
|
229
|
+
data,
|
|
230
|
+
...config
|
|
231
|
+
})
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// delete 请求demo 1 使用params作为参数 参数会拼接在请求路径上
|
|
235
|
+
export function deleteDemo1(
|
|
236
|
+
data = {},
|
|
237
|
+
config = {
|
|
238
|
+
noShowLoading: true // 配置不展示加载动画
|
|
239
|
+
}
|
|
240
|
+
) {
|
|
241
|
+
return axiosOptimize.delete(`/xiaobu-admin/deleteDemo1`, { params: data, ...config })
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// delete 请求 demo 2 使用params作为参数 参数会拼接在请求路径上
|
|
245
|
+
export function deleteDemo2(
|
|
246
|
+
data = {},
|
|
247
|
+
config = {}
|
|
248
|
+
) {
|
|
249
|
+
return axiosOptimize({
|
|
250
|
+
method: 'delete',
|
|
251
|
+
url: `/xiaobu-admin/deleteDemo2`,
|
|
252
|
+
params: data,
|
|
253
|
+
...config
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// delete 请求demo 3 使用data作为参数 参数不展示在 请求路径上
|
|
258
|
+
export function deleteDemo3(data = {}, config = {}) {
|
|
259
|
+
return axiosOptimize.delete(`/xiaobu-admin/deleteDemo3`, { data, ...config })
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// delete 请求 demo 4 使用data作为参数 参数不展示在 请求路径上
|
|
263
|
+
export function deleteDemo4(data = {}, config = {}) {
|
|
264
|
+
return axiosOptimize({
|
|
265
|
+
method: 'delete',
|
|
266
|
+
url: `/xiaobu-admin/deleteDemo4`,
|
|
267
|
+
data,
|
|
268
|
+
...config
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// put 请求demo 1
|
|
273
|
+
export function putDemo1(data = {}, config = {}) {
|
|
274
|
+
return axiosOptimize.put('/xiaobu-admin/putDemo1', data, config)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// put 请求demo 2
|
|
278
|
+
export function putDemo2(data = {}, config = {}) {
|
|
279
|
+
return axiosOptimize({
|
|
280
|
+
url: '/xiaobu-admin/putDemo2',
|
|
281
|
+
method: 'put',
|
|
282
|
+
data,
|
|
283
|
+
...config
|
|
284
|
+
})
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// patch 请求demo 1
|
|
288
|
+
export function patchDemo1(data = {}, config = {}) {
|
|
289
|
+
return axiosOptimize.patch('/xiaobu-admin/patchDemo1', data, config)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// patch 请求demo 2
|
|
293
|
+
export function patchDemo2(data = {}, config = {}) {
|
|
294
|
+
return axiosOptimize({
|
|
295
|
+
url: '/xiaobu-admin/patchDemo2',
|
|
296
|
+
method: 'patch',
|
|
297
|
+
data,
|
|
298
|
+
...config
|
|
299
|
+
})
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## new axiosOptimize(axios, instance, options)参数说明
|
|
305
|
+
|
|
306
|
+
| 参数 | 说明 | 来源 |
|
|
307
|
+
| -------- | ------------------------- | ------------------------------------- |
|
|
308
|
+
| axios | 安装axios中的axios | import axios from 'axios' |
|
|
309
|
+
| instance | 创建好的axios实例,已经配置好请求头等相关内容 | import instance from '@/api/axios.js' |
|
|
310
|
+
| options | 一些配置,详情继续阅读文档 | 自定义配置 |
|
|
311
|
+
|
|
312
|
+
## options配置
|
|
313
|
+
|
|
314
|
+
| 参数 | 类型 | 说明 | 是否必传 | 默认值 |
|
|
315
|
+
| -------------------------------------- | -------- | ---------------------------------------- | -------------------- | ------------------------------ |
|
|
316
|
+
| showLoadingFun(config, requestingNum) | Function | 展示动画,config为该请求的config,requestingNum为目前正在请求几个接口,此处可执行一些展示全局动画的操作 | 否 | 无 |
|
|
317
|
+
| hideLoadingFun(config, requestingNum) | Function | 隐藏动画,config为该请求的config,requestingNum为目前正在请求几个接口,此时应该为0,此处可执行关闭全局动画的操作 | 否 | 无 |
|
|
318
|
+
| openRefresh | Boolean | 是否开启无感知刷新token | 否 | false |
|
|
319
|
+
| refreshApiUrl | String | 请求刷新token接口的api地址 如/xiaobu-admin/refresh-token | 当openRefresh为true时必传 | 无 |
|
|
320
|
+
| getRefreshTokenFun() | Function | 获取当前项目的 refreshToken方法, 记得 return 回去 | 当openRefresh为true时必传 | 无 |
|
|
321
|
+
| reloginFun(response) | Function | response 为axios实例中返回的数据,此处建议执行清除token相关缓存并弹框提示,点击确认进行刷新页面操作 | 当openRefresh为true时必传 | 无 |
|
|
322
|
+
| refreshTokenStore(refreshToken) | Function | refreshToken为当前浏览器缓存的refreshToken,需要返回一个Promise,利用此refreshToken调用接口获取新的accessToken 并设置。 | 当openRefresh为true时必传 | 无 |
|
|
323
|
+
| setAccessTokenFun(config, accessToken) | Function | config为该请求的config,accessToken 为新获取的accessToken, 此处需要将accessToken设置到请求头中 | 当openRefresh为true时必传 | 无 |
|
|
324
|
+
| responseResultFun(res) | Function | res为axios实例返回的res,格式化接口请求成功后返回的数据 | 非必传 | axios实例返回的res |
|
|
325
|
+
| formatAccessTokenFun(data) | Function | data为responseResultFun报错时返回的res | 非必传 | axios实例返回的res.data.accessToken |
|
|
326
|
+
| accessTokenExpirationCode | number | 配置accessToken过期返回的业务状态码 | 非必传 | 401 |
|
|
327
|
+
| refreshTokenExpirationCode | number | 配置refreshToken过期返回的业务状态码 | 非必传 | 403 |
|
|
328
|
+
| responseTypesStr(v1.0.2) | String | 配置数据返回类型,实现当此类型时返回原封不动的响应数据的data数据 | 非必传 | 无 |
|
|
329
|
+
|
|
330
|
+
## store/user.ts代码大致如下
|
|
331
|
+
|
|
332
|
+
```ts
|
|
333
|
+
import { defineStore } from 'pinia'
|
|
334
|
+
import { store } from '@/store'
|
|
335
|
+
import { commonApi } from '@/api'
|
|
336
|
+
import storage, { userKey } from '@/utils/storage'
|
|
337
|
+
import { setCookie, getCookie, removeCookie, accessTokenKey, refreshTokenKey } from '@/utils/cookie'
|
|
338
|
+
import { LoginVO, UserInfoVO, RefreshTokenVO } from '@/api/vo/common-vo'
|
|
339
|
+
import { RefreshTokenDTO } from '@/api/dto/common-dto'
|
|
340
|
+
const storageData = storage.info()
|
|
341
|
+
|
|
342
|
+
const useUserStore = defineStore('user', {
|
|
343
|
+
state: () => {
|
|
344
|
+
return {
|
|
345
|
+
accessToken: getCookie(accessTokenKey) || '',
|
|
346
|
+
refreshToken: getCookie(refreshTokenKey) || '',
|
|
347
|
+
userInfo: storageData[userKey] || null
|
|
348
|
+
}
|
|
349
|
+
},
|
|
350
|
+
|
|
351
|
+
getters: {
|
|
352
|
+
gettersRefreshToken: (state) => {
|
|
353
|
+
return state.refreshToken
|
|
354
|
+
},
|
|
355
|
+
gettersAccessToken: (state) => {
|
|
356
|
+
return state.accessToken
|
|
357
|
+
},
|
|
358
|
+
gettersUserInfo: (state) => {
|
|
359
|
+
return () => state.userInfo
|
|
360
|
+
}
|
|
361
|
+
},
|
|
362
|
+
|
|
363
|
+
actions: {
|
|
364
|
+
// 设置cookie
|
|
365
|
+
setToken(data: LoginVO) {
|
|
366
|
+
this.accessToken = data.accessToken
|
|
367
|
+
setCookie(accessTokenKey, data.accessToken, data.expiresIn)
|
|
368
|
+
this.refreshToken = data.refreshToken
|
|
369
|
+
setCookie(refreshTokenKey, data.refreshToken, data.expiresIn)
|
|
370
|
+
},
|
|
371
|
+
// 清除AccessToken及RefreshToken
|
|
372
|
+
clearAuth() {
|
|
373
|
+
this.accessToken = ''
|
|
374
|
+
removeCookie(accessTokenKey)
|
|
375
|
+
this.refreshToken = ''
|
|
376
|
+
removeCookie(refreshTokenKey)
|
|
377
|
+
this.userInfo = null
|
|
378
|
+
storage.remove(userKey)
|
|
379
|
+
},
|
|
380
|
+
// 刷新token
|
|
381
|
+
async refreshTokenAction(params: RefreshTokenDTO) {
|
|
382
|
+
return new Promise<RefreshTokenVO>((resolve, reject) => {
|
|
383
|
+
commonApi
|
|
384
|
+
.refreshToken(params)
|
|
385
|
+
.then((data) => {
|
|
386
|
+
this.setToken(data)
|
|
387
|
+
resolve(data)
|
|
388
|
+
})
|
|
389
|
+
.catch((err) => {
|
|
390
|
+
reject(err)
|
|
391
|
+
})
|
|
392
|
+
})
|
|
393
|
+
},
|
|
394
|
+
|
|
395
|
+
// 获取用户信息
|
|
396
|
+
async getUserInfo() {
|
|
397
|
+
return new Promise<UserInfoVO>((resolve, reject) => {
|
|
398
|
+
commonApi
|
|
399
|
+
.getUserInfo()
|
|
400
|
+
.then((data) => {
|
|
401
|
+
this.userInfo = data
|
|
402
|
+
storage.set(userKey, data)
|
|
403
|
+
resolve(data)
|
|
404
|
+
})
|
|
405
|
+
.catch((err) => {
|
|
406
|
+
reject(err)
|
|
407
|
+
})
|
|
408
|
+
})
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
export function useUserStoreHook() {
|
|
414
|
+
return useUserStore(store)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
## 注意
|
|
420
|
+
|
|
421
|
+
如果要配置无感知刷新token时,对后端是有要求的,需要做到当accessToken过期refreshToken未过期时,请求接口的业务状态码 code为 配置的 accessTokenExpirationCode 的值, 默认401,当refreshToken过期或其他问题报错导致系统无法运行的错误时 业务状态码code 应为配置的 refreshTokenExpirationCode, 默认403
|
|
422
|
+
|
|
423
|
+
当部分页面接口请求在catch处有操作时 需添加语句, 参考如下示例
|
|
424
|
+
|
|
425
|
+
```js
|
|
426
|
+
this.loading = true
|
|
427
|
+
testApi.getUserList(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
|
|
428
|
+
const response = res.data
|
|
429
|
+
this.list = response.rows
|
|
430
|
+
this.total = response.total
|
|
431
|
+
this.loading = false
|
|
432
|
+
}).catch(err => {
|
|
433
|
+
// 此处需要添加 如果是取消请求 或者是 阻止请求时 不进行操作
|
|
434
|
+
if (err.isPrevent || err?.message?.isCancel) {
|
|
435
|
+
return
|
|
436
|
+
}
|
|
437
|
+
this.loading = false
|
|
438
|
+
})
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## 特别注意
|
|
442
|
+
|
|
443
|
+
vue2项目的vue.config.js 需要添加如下配置,对插件包进行编译。
|
|
444
|
+
|
|
445
|
+
```js
|
|
446
|
+
module.exports = {
|
|
447
|
+
...
|
|
448
|
+
transpileDependencies: [
|
|
449
|
+
"vue-axios-optimize"
|
|
450
|
+
],
|
|
451
|
+
...
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
## 总结
|
|
456
|
+
|
|
457
|
+
如有疑问,可关注微信公众号【爆米花小布】进行咨询。
|
|
458
|
+
|
|
459
|
+

|
|
460
|
+
|
|
461
|
+
微信公众号【爆米花小布】,抖音号【爆米花小布】 更多好玩的插件
|
|
462
|
+
|
|
463
|
+
[vue2-element-dict字典包插件](https://www.npmjs.com/package/vue2-element-dict)
|
|
464
|
+
|
|
465
|
+
[vue3-element-dict字典包插件](https://www.npmjs.com/package/vue3-element-dict)
|
|
466
|
+
|
|
467
|
+
[vue2-vant-dict移动端字典包插件](https://www.npmjs.com/package/vue2-vant-dict)
|
|
468
|
+
|
|
469
|
+
[vue3-water-marker水印插件](https://www.npmjs.com/package/vue3-water-marker)
|
|
470
|
+
|
|
471
|
+
[vue2-water-marker水印插件](https://www.npmjs.com/package/vue2-water-marker)
|
|
472
|
+
|
|
473
|
+
## 更新日志
|
|
474
|
+
|
|
475
|
+
### 1.0.2
|
|
476
|
+
|
|
477
|
+
1. options新增responseTypesStr配置项,字符串类型,多个时使用英文逗号隔开,此返回类型的数据直接返回原有数据的data数据。在axios.js原封装函数中返回原始的响应返回数据。解决文件类型数据时不可用的问题
|
|
478
|
+
|
|
479
|
+
### 1.0.1
|
|
480
|
+
|
|
481
|
+
1. 修复单词错误问题 isPervent 修改为 isPrevent
|
|
482
|
+
|
|
483
|
+
### 1.0.0
|
|
484
|
+
|
|
477
485
|
1. 初始版本
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class e{instance;requestObj={};requestingNum=0;authErrorArr=[];queue=[];isRefresh=!1;isShowReLoginDialog=!1;constructor(e,s,r){this.instance=s,this.instance.interceptors.request.use((s=>{s.noShowLoading||(this.requestingNum++,r.showLoadingFun&&r.showLoadingFun(s,this.requestingNum));const
|
|
1
|
+
class e{instance;requestObj={};requestingNum=0;authErrorArr=[];queue=[];isRefresh=!1;isShowReLoginDialog=!1;constructor(e,s,r){this.instance=s,this.instance.interceptors.request.use((s=>{s.noShowLoading||(this.requestingNum++,r.showLoadingFun&&r.showLoadingFun(s,this.requestingNum));const t=s.url;if(r.openRefresh){-1===this.authErrorArr.indexOf(t)&&this.isRefresh&&t!==r.refreshApiUrl&&this.authErrorArr.push(t)}if(t&&s.preventDuplicateRequestsType)if("cancel"===s.preventDuplicateRequestsType){this.requestObj[t]&&this.requestObj[t].cancel({config:s,isCancel:!0});const r=e.CancelToken;this.requestObj[t]=r.source(),s.cancelToken=this.requestObj[t].token}else if("prevent"===s.preventDuplicateRequestsType){if("requesting"===this.requestObj[t])return Promise.reject({config:s,isPrevent:!0});this.requestObj[t]="requesting"}return s}),(e=>Promise.reject(e))),this.instance.interceptors.response.use((async e=>{const{config:s,responseErr:t}=e;if(s.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},r.hideLoadingFun&&r.hideLoadingFun(s,this.requestingNum))),s&&this.requestObj[s.url]&&delete this.requestObj[s.url],t){if(r.openRefresh){const t=this.authErrorArr.indexOf(s.url);if(-1!==t)return this.authErrorArr.splice(t,1),new Promise((e=>{this.queue.push((t=>{r.setAccessTokenFun(s,t),e(this.instance.request(s))}))}));const i=r.accessTokenExpirationCode||401;if(Number(e.code)===i){const t=r.getRefreshTokenFun();if(!t){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,r.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}if(this.isRefresh)return new Promise((e=>{this.queue.push((t=>{r.setAccessTokenFun(s,t),e(this.instance.request(s))}))}));this.isRefresh=!0;try{const e=await r.refreshTokenStore(t);let i=null;return i=r.formatAccessTokenFun?r.formatAccessTokenFun(e):e.data.accessToken,this.queue.forEach((e=>e(i))),this.instance.request(s)}catch{if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,r.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}finally{this.queue=[],this.isRefresh=!1}}const n=r.refreshTokenExpirationCode||403;if(Number(e.code)===n){if(this.isShowReLoginDialog)return;return this.isShowReLoginDialog=!0,r.reloginFun(e),Promise.reject(new Error(e.message||"Error"))}}return Promise.reject(new Error(e.message||"Error"))}if(r.responseTypesStr?.toLocaleLowerCase().split(",").includes(s.responseType?.toLocaleLowerCase()))return e.data;const i=JSON.parse(JSON.stringify(e));return delete i.responseErr,r.responseResultFun?r.responseResultFun(i):i}),(e=>{const s=e.config||e?.message?.config||{};return s.noShowLoading||(this.requestingNum--,this.requestingNum<=0&&(this.requestObj={},r.hideLoadingFun&&r.hideLoadingFun(s,this.requestingNum))),e.isPrevent||e?.message?.isCancel||delete this.requestObj[s.url],Promise.reject(e)}))}}export default e;
|
package/package.json
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "vue-axios-optimize",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "vue项目对axios请求的优化,实现可配置展示全局加载动画,可配置是否重复请求时取消前面的请求或者阻止后面的请求。",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
|
|
8
|
-
},
|
|
9
|
-
"keywords": [
|
|
10
|
-
"vue",
|
|
11
|
-
"axios",
|
|
12
|
-
"vue3",
|
|
13
|
-
"vue2"
|
|
14
|
-
],
|
|
15
|
-
"author": "沈延祥",
|
|
16
|
-
"license": "ISC"
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-axios-optimize",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "vue项目对axios请求的优化,实现可配置展示全局加载动画,可配置是否重复请求时取消前面的请求或者阻止后面的请求。",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"vue",
|
|
11
|
+
"axios",
|
|
12
|
+
"vue3",
|
|
13
|
+
"vue2"
|
|
14
|
+
],
|
|
15
|
+
"author": "沈延祥",
|
|
16
|
+
"license": "ISC"
|
|
17
|
+
}
|