事出有因
通常在 vue-cli 腳手架 src 目錄下,有一個 api 資料夾,用來存放被抽離出的 API 請求,如下圖所示:

其中 module 資料夾下存放各模組抽離的 API,axios.ts 檔案建立 axios 的一個例項,並新增一些公共配置(如:baseURL, timeout,攔截器等),index.ts 即是向外暴露各種 API 方法。
module 下的每個檔案內容格式基本都一樣:

get 請求傳引數有點不同:
export function getSome (
params?: any
): Promise<Ajax.AjaxResponse> {
return ax.get('/some', { params })
.then(res => res.data)
.catch(error => console.error(error))
}
複製程式碼
當專案越來越大,module 下的檔案越來越多時(但檔案內容基本一樣),本著能少寫程式碼就少寫程式碼的我,冒出一個想法,是否能通過一個 json 檔案,來生成所需要的檔案?如下圖:

定義一個如上 json 檔案,執行一段指令碼,它就可以生成包含下圖程式碼檔案:

那就開始吧
我們的目的很簡單,讀取一個 json 檔案,把 json 檔案裡對應欄位的值,寫入到一個 .ts 檔案裡。
這裡,我們用到 node 的 fs 模組,用來讀取與寫入檔案。
// index.js
const fs = require('fs')
// 讀取 json 檔案
const data = fs.readFileSync(`user.json`)
// parse 匯入檔案
const content = JSON.parse(data)
複製程式碼
定義每個函式的 template:
const template = item => {
return `// ${item.des}\n` +
`export function ${item.name} (params?: any)` +
`: Promise<Ajax.AjaxResponse> {\n` +
` return ax.${item.method}('${item.url}', ` +
`${item.method === 'get' ? '{ params }' : 'params'})\n` +
` .then(res => res.data)\n` +
` .catch(error => console.error)\n` +
`}\n\n`
}
複製程式碼
接著遍歷 content
let result = "import ax from '../axios'\n\n"
content.forEach(item => {
result += template(item)
})
// 生成檔案
fs.writeFileSync(`user.ts`, result)
複製程式碼
執行命令 node index.js
,發現這次嘗試是成功的:

實際中,module 應該是很多個,而且輸出檔案的名字,應該是與對應 json 檔案的名字是相同的。就像下圖一樣:

我們來改動一下前面所寫的程式碼:
const fs = require('fs')
const path = require('path')
// 入口資料夾
const enPath = path.resolve(__dirname, '../src/ajax')
// 出口資料夾
const outPath = path.resolve(__dirname, '../src/api/module')
// 目錄不存在時,建立
if (!fs.existsSync(outPath)) {
fs.mkdirSync(outPath)
}
const template = item => {
return `// ${item.des}\n` +
`export function ${item.name} (params?: any)` +
`: Promise<Ajax.AjaxResponse> {\n` +
` return ax.${item.method}('${item.url}', ` +
`${item.method === 'get' ? '{ params }' : 'params'})\n` +
` .then(res => res.data)\n` +
` .catch(error => console.error)\n` +
`}\n\n`
}
// 讀取資料夾
const files = fs.readdirSync(enPath)
// 讀取單個檔案,生成所需檔案
files.forEach(file => {
const data = fs.readFileSync(`${enPath}/${file}`)
const fileName = file.split('.')[0]
let result = ''
if (data.length) {
result = "import ax from '../axios'\n\n"
const content = JSON.parse(data)
content.forEach(item => {
result += template(item)
})
}
fs.writeFileSync(`${outPath}/${fileName}.ts`, result)
console.log(`寫入檔案成功:${outPath}/${fileName}.ts`)
})
複製程式碼
執行命令 node index.js
,自此,就基本達成了最初的目的。
實際過程中,可能並沒什麼卵用,比如說某些請求裡,需要加不同的配置( baseURL, header 等),還有可能資料夾 ajax 下還細分了資料夾等。不過,折騰一下,總能出來。