一渠缕、代碼規(guī)范
1.1 vscode集成editorconfig
安裝editorconfig插件后慢蜓,在項(xiàng)目根目錄下生成如下配置
.editorconfig
# http://editorconfig.org
root = true
[*] # 表示所有文件適用
charset = utf-8 # 設(shè)置文件字符集為 utf-8
indent_style = space # 縮進(jìn)風(fēng)格(tab | space)
indent_size = 2 # 縮進(jìn)大小
end_of_line = lf # 控制換行類型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始終在文件末尾插入一個(gè)新行
[*.md] # 表示僅 md 文件適用以下規(guī)則
max_line_length = off
trim_trailing_whitespace = false
1.2 使用prettier格式化工具
Prettier 是一款強(qiáng)大的代碼格式化工具谍椅,支持 JavaScript笨觅、TypeScript赠橙、CSS髓介、SCSS凯砍、Less箱硕、JSX、Angular悟衩、Vue剧罩、GraphQL、JSON座泳、Markdown 等語言惠昔,基本上前端能用到的文件格式它都可以搞定,是當(dāng)下最流行的代碼格式化工具挑势。
-
安裝prettier
npm install prettier -D
-D 就是npm install --save-dev 表示改依賴只在開發(fā)環(huán)境中
-
prettier配置文件
.prettierrc
- useTabs:使用tab縮進(jìn)還是空格縮進(jìn)镇防,選擇false;
- tabWidth:tab是空格的情況下薛耻,是幾個(gè)空格营罢,選擇2個(gè);
- printWidth:當(dāng)行字符的長(zhǎng)度饼齿,推薦80饲漾,也有人喜歡100或者120;
- singleQuote:使用單引號(hào)還是雙引號(hào)缕溉,選擇true考传,使用單引號(hào);
- trailingComma:在多行輸入的尾逗號(hào)是否添加证鸥,設(shè)置為
none
僚楞; - semi:語句末尾是否要加分號(hào),默認(rèn)值true枉层,選擇false表示不加泉褐;
.prettierrc
{ "useTabs": false, "tabWidth": 2, "printWidth": 80, "singleQuote": true, "trailingComma": "none", "semi": false }
-
prettier忽略文件
.prettierignore
/dist/* .local .output.js /node_modules/** **/*.svg **/*.sh /public/*
-
在
package.json
中添加格式化所有文件的腳本"prettier": "prettier --write ."
1.3 使用ESLint檢測(cè)
如果使用
vue cli
創(chuàng)建項(xiàng)目的時(shí)候選擇了ESLint
,則vue會(huì)默認(rèn)配置好ESLint
所需的環(huán)境vscode安裝
ESLint
插件-
解決
ESLint
和prettier
之間的沖突vue cli
創(chuàng)建的項(xiàng)目中鸟蜡,ESLint
的規(guī)范是vue
團(tuán)隊(duì)的膜赃,如果我們想要用自己的ESLint
配置,則會(huì)和他們的規(guī)范沖突揉忘,這樣一來prettier
格式化后就會(huì)和ESLint
的不一致跳座,為了解決這個(gè)問題端铛,需要安裝如下兩個(gè)插件npm i eslint-plugin-prettier eslint-config-prettier -D
這兩個(gè)插件如果在
vue cli
創(chuàng)建項(xiàng)目時(shí)選擇了ESLint + prettier
,則會(huì)默認(rèn)幫我們裝上的將插件添加到.eslintrc.js
extends: [ 'plugin:vue/vue3-essential', 'eslint:recommended', '@vue/typescript/recommended', '@vue/prettier', '@vue/prettier/@typescript-eslint', 'plugin:prettier/recommended' ],
即在最后一行加上
'plugin:prettier/recommended'
即可
1.4 git Husky保證提交代碼的規(guī)范
雖然我們已經(jīng)要求項(xiàng)目使用eslint了疲眷,但是不能保證組員提交代碼之前都將eslint中的問題解決掉了:
- 也就是我們希望保證代碼倉庫中的代碼都是符合eslint規(guī)范的禾蚕;
- 那么我們需要在組員執(zhí)行
git commit
命令的時(shí)候?qū)ζ溥M(jìn)行校驗(yàn),如果不符合eslint規(guī)范狂丝,那么自動(dòng)通過規(guī)范進(jìn)行修復(fù)换淆;husky是一個(gè)git hook工具,可以幫助我們觸發(fā)git提交的各個(gè)階段:pre-commit美侦、commit-msg产舞、pre-push
這里我們可以使用自動(dòng)配置命令:
npx husky-init && npm install
該命令會(huì)做三件事:
添加
husky
項(xiàng)目依賴到package.json
中的devDependencies
中-
在項(xiàng)目目錄下創(chuàng)建
.husky
文件夾,該文件夾中存放hook配置菠剩,也可以手動(dòng)執(zhí)行下面的命令進(jìn)行創(chuàng)建npx huksy install
-
在
package.json
中添加一個(gè)腳本"prepare": "husky install"
接下來易猫,我們需要去完成一個(gè)操作:在進(jìn)行commit時(shí),執(zhí)行package.json
中的lint腳本具壮,這時(shí)候就需要修改hook
配置了
打開.hucky
中的pre-commit
配置文件准颓,將原本的npm test
改成npm run lint
即可
1.5 git commit規(guī)范
-
Commitizen
用于編寫規(guī)范的commit message
-
commitlint
用于檢查提交的信息是否符合規(guī)范,用于避免提交的時(shí)候是直接git commit -m "xxx"
棺妓,而不是通過Commitizen
時(shí)的情況
1.5.1 Commitizen
-
安裝
Commitizen
npm install commitizen -D
-
安裝
cz-conventional-changelog
攘已,并且初始化cz-conventional-changelog
npx commitizen init cz-conventional-changelog --save-dev --save-exact
該命令會(huì)安裝
cz-conventional-changelog
并在package.json
中進(jìn)行配置 -
現(xiàn)在提交代碼就可以使用
npx cz
提交,提交的message
就是規(guī)范的了-
type
Type 作用 feat 新增特性 (feature) fix 修復(fù) Bug(bug fix) docs 修改文檔 (documentation) style 代碼格式修改(white-space, formatting, missing semi colons, etc) refactor 代碼重構(gòu)(refactor) perf 改善性能(A code change that improves performance) test 測(cè)試(when adding missing tests) build 變更項(xiàng)目構(gòu)建或外部依賴(例如 scopes: webpack怜跑、gulp样勃、npm 等) ci 更改持續(xù)集成軟件的配置文件和 package 中的 scripts 命令,例如 scopes: Travis, Circle 等 chore 變更構(gòu)建流程或輔助工具(比如更改測(cè)試環(huán)境) revert 代碼回退
-
1.5.2 commitlint
-
安裝 @commitlint/config-conventional 和 @commitlint/cli
npm i @commitlint/config-conventional @commitlint/cli -D
-
在根目錄創(chuàng)建commitlint.config.js文件性芬,配置commitlint
module.exports = { extends: ['@commitlint/config-conventional'] }
-
使用husky生成commit-msg文件峡眶,驗(yàn)證提交信息:
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
二、第三方集成
2.1 vue.config.js配置
vue.config.js有三種配置方式:
- 方式一:直接通過CLI提供給我們的選項(xiàng)來配置:
- 比如publicPath:配置應(yīng)用程序部署的子目錄(默認(rèn)是
/
植锉,相當(dāng)于部署在https://www.my-app.com/
)辫樱;- 比如outputDir:修改輸出的文件夾;
- 方式二:通過configureWebpack修改webpack的配置:
- 可以是一個(gè)對(duì)象俊庇,直接會(huì)被合并狮暑;
- 可以是一個(gè)函數(shù),會(huì)接收一個(gè)config辉饱,可以通過config來修改配置搬男;
- 方式三:通過chainWebpack修改webpack的配置:
- 是一個(gè)函數(shù),會(huì)接收一個(gè)基于 webpack-chain 的config對(duì)象彭沼,可以對(duì)配置進(jìn)行修改止后;
示例
const path = require('path')
module.exports = {
// 配置方式一
outputDir: './build',
// 配置方式二:對(duì)象形式
configureWebpack: {
resolve: {
alias: {
views: '@/views'
}
}
}
// 配置方式三:函數(shù)形式
configureWebpack: (config) => {
config.resolve.alias = {
'@': path.resolve(__dirname, 'src'),
views: '@/views'
}
},
// 配置方式四:鏈?zhǔn)秸{(diào)用形式
chainWebpack: (config) => {
config.resolve.alias.set('@', path.resolve(__dirname, 'src')).set('views', '@/views')
}
}
遇到明確沒問題的ESLint提示
比如這里的const path = require('path')
,ESLint會(huì)提示使用ES風(fēng)格的import替代溜腐,但是由于是給node用的配置文件译株,必須是commonJS風(fēng)格的,這個(gè)時(shí)候我們需要把這一條ESLint提示禁用掉
vscode中將鼠標(biāo)懸停在提示的代碼處挺益,會(huì)彈出對(duì)應(yīng)的ESLint提示項(xiàng)歉糜,比如這里的提示就是@typescript-eslint/no-var-requires
將它復(fù)制下來,打開.eslintrc.js
望众,在rules
中添加該配置項(xiàng)匪补,并且值設(shè)為off
即可關(guān)閉
rules: {
'@typescript-eslint/no-var-requires': 'off'
}
2.2 vue-router集成
-
安裝
vue-router
npm install vue-router@4
-
創(chuàng)建文件 --
src/router/index.ts
index.ts
import { createRouter, createWebHashHistory } from 'vue-router' import { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw[] = [ { path: '/', redirect: '/main' }, { path: '/main', component: () => import('@/views/main/main.vue') }, { path: '/login', component: () => import('@/views/login/login.vue') } ] const router = createRouter({ routes, history: createWebHashHistory() }) export default router
-
在
main.ts
中注冊(cè)main.ts
import { createApp } from 'vue' import App from './App.vue' import router from '@/router' const app = createApp(App) app.use(router) app.mount('#app')
-
App.vue
中配置路由跳轉(zhuǎn)<template> <div class="app"> <router-link to="/login">登錄</router-link> <router-link to="/main">首頁</router-link> <router-view></router-view> </div> </template>
2.3 vuex集成
-
安裝vuex
npm install vuex@next --save
-
創(chuàng)建文件 --
src/store/index.ts
index.ts
import { createStore } from 'vuex' const store = createStore({ state() { return { name: 'plasticine' } } }) export default store
-
在
main.ts
中注冊(cè)app.use(store)
-
在
App.vue
中使用<h1>{{ $store.state.name }}</h1>
2.4 element-plus集成
-
安裝
element-plus
npm install element-plus --save
引入
element-plus
2.4.1 完整引入
// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
2.4.2按需引入
-
安裝兩個(gè)插件
npm install -D unplugin-vue-components unplugin-auto-import
-
修改
vue.config.js
中的Webpack配置const AutoImport = require('unplugin-auto-import/webpack') const Components = require('unplugin-vue-components/webpack') const { ElementPlusResolver } = require('unplugin-vue-components/resolvers') module.exports = { configureWebpack: { plugins: [ AutoImport({ resolvers: [ElementPlusResolver()] }), Components({ resolvers: [ElementPlusResolver()] }) ] } }
-
在
main.ts
中注冊(cè)全局組件main.ts
import { ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge } from 'element-plus' const app = createApp(App) const components = [ ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge ] for (const cpn of components) { app.component(cpn.name, cpn) }
這樣的話雖然能用,但是隨著開發(fā)進(jìn)度的進(jìn)行烂翰,引用的組件越來越多夯缺,會(huì)導(dǎo)致
main.ts
文件過于臃腫,作為入口文件甘耿,應(yīng)當(dāng)盡量只包括主要邏輯踊兜,不應(yīng)該包含過多的邏輯代碼,因此現(xiàn)在我們對(duì)其進(jìn)行抽離 -
創(chuàng)建文件 --
src/global/index.ts
index.ts
import { ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge } from 'element-plus' import { App } from 'vue' const components = [ ElButton, ElTable, ElAlert, ElAside, ElAutocomplete, ElAvatar, ElBacktop, ElBadge ] export function registerApp(app: App): void { for (const cpn of components) { app.component(cpn.name, cpn) } }
導(dǎo)出一個(gè)函數(shù)
registerApp
佳恬,在main.ts
中只用調(diào)用該函數(shù)即可main.ts
import { createApp } from 'vue' import App from './App.vue' import { registerApp } from '@/global' const app = createApp(App) registerApp(app) app.mount('#app')
其實(shí)還可以進(jìn)一步抽離捏境,因?yàn)橐院罂赡苓€要注冊(cè)別的組件,這時(shí)候如果全部注冊(cè)邏輯寫在單個(gè)
registerApp
函數(shù)里就又會(huì)變得臃腫了毁葱,因此將每個(gè)組件庫的組件注冊(cè)再次抽離成一個(gè)文件垫言,如現(xiàn)在要注冊(cè)element-plus
,那么我們就在global
目錄下創(chuàng)建一個(gè)register-element.ts
倾剿,然后把注冊(cè)邏輯寫在里面筷频,registerApp
去調(diào)用即可
`register-element.ts`
```typescript
import { App } from 'vue'
import {
ElButton,
ElTable,
ElAlert,
ElAside,
ElAutocomplete,
ElAvatar,
ElBacktop,
ElBadge
} from 'element-plus'
const components = [
ElButton,
ElTable,
ElAlert,
ElAside,
ElAutocomplete,
ElAvatar,
ElBacktop,
ElBadge
]
export default function (app: App): void {
for (const cpn of components) {
app.component(cpn.name, cpn)
}
}
```
`src/global/index.ts`
```typescript
import { App } from 'vue'
import registerElement from './register-element'
export function registerApp(app: App): void {
registerElement(app)
}
```
-
App.vue
中直接使用<el-button>element-plus 按鈕</el-button>
-
更優(yōu)雅地注冊(cè)
Vue的
app.use()
會(huì)默認(rèn)傳入app
,因此可以進(jìn)行如下調(diào)整前痘,讓代碼風(fēng)格更加統(tǒng)一
`main.ts`
```typescript
import { createApp } from 'vue'
import App from './App.vue'
import { globalRegister } from '@/global'
const app = createApp(App)
app.use(globalRegister)
app.mount('#app')
```
`src/global/index.ts`
```typescript
import { App } from 'vue'
import registerElement from './register-element'
export function globalRegister(app: App): void {
app.use(registerElement)
}
```
2.5 axios集成
2.5.1 安裝axios
npm install axios
2.5.2 創(chuàng)建文件 -- src/service/request/config.ts
該文件用于存放一些axios
用到的配置項(xiàng)凛捏,如BASE_URL
等
/**
* 生產(chǎn)環(huán)境 -- production
* 開發(fā)環(huán)境 -- development
* 測(cè)試環(huán)境 -- test
*/
let BASE_URL = ''
const TIME_OUT = 10000
switch (process.env.NODE_ENV) {
case 'development':
BASE_URL = 'http://123.207.32.32:8000'
break
case 'production':
BASE_URL = 'https://www.baidu.com/'
break
case 'test':
BASE_URL = 'https://www.baidu.com/'
break
}
export { BASE_URL, TIME_OUT }
2.5.3 封裝AxiosInstance
封裝AxiosInstance
實(shí)例對(duì)象,主要是添加對(duì)各種攔截器的支持际度,攔截器的粒度細(xì)致到以下三個(gè)階段:
- 全局請(qǐng)求響應(yīng)攔截葵袭,對(duì)所有的請(qǐng)求都生效
- 實(shí)例請(qǐng)求響應(yīng)攔截,針對(duì)不同的實(shí)例可以設(shè)置不同的請(qǐng)求響應(yīng)攔截
- 單獨(dú)請(qǐng)求響應(yīng)攔截乖菱,針對(duì)具體接口設(shè)置相應(yīng)的請(qǐng)求響應(yīng)攔截
要實(shí)現(xiàn)上述攔截器坡锡,需要自己封裝一個(gè)攔截器類型接口,分別對(duì)應(yīng)請(qǐng)求成功處理窒所、請(qǐng)求失敗處理鹉勒、響應(yīng)成功處理、響應(yīng)失敗處理
因此再創(chuàng)建一個(gè)文件吵取,用于存放用到的接口類型 -- src/service/request/type.ts
import { AxiosRequestConfig, AxiosResponse } from 'axios'
export interface WFRequestInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: any) => any
responseInterceptor?: (res: T) => T
responseInterceptorCatch?: (error: any) => any
}
export interface WFRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {
interceptors?: WFRequestInterceptors<T>
showLoading?: boolean
}
創(chuàng)建一個(gè)類用于封裝AxiosInstance
實(shí)例禽额,這個(gè)類存放在 src/service/request/index.ts
中并默認(rèn)導(dǎo)出
src/service/request/index.ts
import axios from 'axios'
import { ElLoading } from 'element-plus'
import type { AxiosInstance } from 'axios'
import { WFRequestConfig, WFRequestInterceptors } from './type'
import { DEAFAULT_LOADING } from './config'
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
class WFRequest {
instance: AxiosInstance
interceptors?: WFRequestInterceptors
showLoading: boolean // 處理請(qǐng)求時(shí)是否要顯示加載動(dòng)畫
loading?: LoadingInstance
constructor(config: WFRequestConfig) {
// 創(chuàng)建 axios 實(shí)例
this.instance = axios.create(config)
// 保存基本信息
this.showLoading = config.showLoading ?? DEAFAULT_LOADING
this.interceptors = config.interceptors
// ================== 屬于實(shí)例的攔截器 ==================
// 將請(qǐng)求攔截器注冊(cè)到 axios 實(shí)例中
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
// 將請(qǐng)求攔截器注冊(cè)到 axios 實(shí)例中
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
// ================== 所有實(shí)例的攔截器 ==================
// 所有實(shí)例的請(qǐng)求攔截器
this.instance.interceptors.request.use(
(config) => {
console.log('所有的實(shí)例都有的攔截器: 請(qǐng)求成功攔截')
// 處理加載動(dòng)畫
if (this.showLoading) {
this.loading = ElLoading.service({
lock: true,
text: '正在請(qǐng)求數(shù)據(jù)......',
background: 'rgba(0, 0, 0, 0.5)'
})
}
return config
},
(err) => {
console.log('所有的實(shí)例都有的攔截器: 請(qǐng)求成功攔截')
return err
}
)
// 所有實(shí)例的響應(yīng)攔截器
this.instance.interceptors.response.use(
(res) => {
console.log('所有的實(shí)例都有的攔截器: 響應(yīng)成功攔截')
// 如果有加載動(dòng)畫則將加載動(dòng)畫移除
this.loading?.close()
// 從 res 中提出 data 返回 因?yàn)?data 才是前端真正需要的,其他的東西是 axios 自己封裝的 基本用不到
const data = res.data
return data
},
(err) => {
console.log('所有的實(shí)例都有的攔截器: 響應(yīng)失敗攔截')
this.loading?.close()
// HTTP 的狀態(tài)碼要在失敗響應(yīng)攔截器中攔截
if (err.response.status === 404) {
console.log('404 not found...')
}
return err
}
)
}
request<T>(config: WFRequestConfig<T>): Promise<T> {
return new Promise((resolve, reject) => {
// 單個(gè)請(qǐng)求如果配置了請(qǐng)求攔截器 則先執(zhí)行其配置的請(qǐng)求攔截器 再執(zhí)行全局的請(qǐng)求攔截器
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
// 判斷是否要顯示 loading
if (config.showLoading === false) {
this.showLoading = config.showLoading
}
this.instance
.request<any, T>(config)
.then((res) => {
// 如果單次請(qǐng)求配置了響應(yīng)攔截器 則執(zhí)行實(shí)例的響應(yīng)攔截器
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
// 將 showLoading 設(shè)置為 true -- 這樣就不會(huì)影響下一個(gè)請(qǐng)求了
this.showLoading = DEAFAULT_LOADING
resolve(res)
})
.catch((err) => {
// 將 showLoading 設(shè)置為 true -- 這樣就不會(huì)影響下一個(gè)請(qǐng)求了
this.showLoading = DEAFAULT_LOADING
reject(err)
return err
})
})
}
get<T>(config: WFRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
post<T>(config: WFRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
put<T>(config: WFRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PUT' })
}
delete<T>(config: WFRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
patch<T>(config: WFRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PATCH' })
}
}
export default WFRequest
2.5.3.1使用泛型T的原因
這里使用到的泛型T,意思是在調(diào)用request方法后返回的對(duì)象類型是由axios的AxiosResponse
封裝好的T脯倒,即調(diào)用返回對(duì)象的data屬性拿到的就是T類型的對(duì)象实辑,這點(diǎn)可以通過源碼驗(yàn)證:
request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig<D>): Promise<R>;
而這里調(diào)用request時(shí),傳入的泛型為request<any, T>
藻丢,目的是不讓axios幫我們封裝成AxiosResponse
實(shí)例剪撬,而是直接返回我們需要的泛型對(duì)象T(會(huì)由Promise封裝)
因此then
的res
類型就是T
,然后再在調(diào)用單個(gè)請(qǐng)求的攔截器的時(shí)候:
export interface WFRequestInterceptors<T = AxiosResponse> {
...
responseInterceptor?: (res: T) => T
}
此時(shí)響應(yīng)攔截器接收到的參數(shù)類型就是T悠反,T默認(rèn)就是AxiosResponse
残黑,而一旦我們更改為自己想要的T類型,則不會(huì)再傳入和返回AxiosResponse
類型的對(duì)象
之所以要折騰這么一大長(zhǎng)串代碼斋否,是因?yàn)橐獙?shí)現(xiàn)一個(gè)功能:讓調(diào)用接口的時(shí)候得到的返回值是預(yù)先定義好的后端接口會(huì)返回的數(shù)據(jù)格式的接口對(duì)象梨水,這樣在調(diào)用者看來,就能有如下體驗(yàn):
// 可以指定接口返回的對(duì)象類型
interface DataType {
data: any
returnCode: string
success: boolean
}
wfRequest
.get<DataType>({
url: '/home/multidata'
})
.then((res) => {
console.log(res)
console.log(res.data)
console.log(res.returnCode)
console.log(res.success)
})
調(diào)用者在then
中拿到的不再是AxiosResponse
對(duì)象茵臭,而是調(diào)用get方法時(shí)傳入的DataType泛型對(duì)象
2.5.3.2 service中實(shí)例化封裝好的類
在src/service/index.ts
中實(shí)例化一個(gè)WFRequest
的對(duì)象疫诽,并將其導(dǎo)出以供使用
import WFRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'
const wfRequest = new WFRequest({
baseURL: BASE_URL,
timeout: TIME_OUT,
interceptors: {
requestInterceptor: (config) => {
// 給該實(shí)例發(fā)起的所有請(qǐng)求攜帶上 token
const token = 'temp_token'
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
console.log('單個(gè)實(shí)例請(qǐng)求成功的攔截')
return config
},
requestInterceptorCatch: (err) => {
console.log('單個(gè)實(shí)例請(qǐng)求失敗的攔截')
return err
},
responseInterceptor: (res) => {
console.log('響應(yīng)成功的攔截')
return res
},
responseInterceptorCatch: (err) => {
console.log('響應(yīng)失敗的攔截')
return err
}
}
})
export default wfRequest
2.5.3.3 體驗(yàn)
在項(xiàng)目的main.ts
中使用體驗(yàn)一下
import wfRequest from './service'
// 可以指定接口返回的對(duì)象類型
interface DataType {
data: any
returnCode: string
success: boolean
}
wfRequest.get<DataType>({
url: '/home/multidata',
interceptors: {
requestInterceptor: (config) => {
console.log('單獨(dú)請(qǐng)求的攔截器')
return config
},
responseInterceptor: (res) => {
console.log('單獨(dú)響應(yīng)的攔截器')
console.log(res.returnCode)
console.log(res.success)
console.log(res.data)
return res
}
}
})