Node在項(xiàng)目中應(yīng)用案例之給幾百個(gè)下拉框統(tǒng)一加Filterable實(shí)現(xiàn)可搜索
問(wèn)題描述
- 最近接手一個(gè)老項(xiàng)目,vue2+elementUI+webpack+...技術(shù)棧。
- 主要做的就是改改bug,優(yōu)化一下,提升用戶(hù)的使用體驗(yàn)。
- nvm改一下node版本,npm裝一下依賴(lài),跑起來(lái),然后點(diǎn)一點(diǎn),看看長(zhǎng)什么樣子。
- 上來(lái)筆者就發(fā)現(xiàn)了一個(gè)可以?xún)?yōu)化的點(diǎn),就是:項(xiàng)目中有下拉框el-select組件,可前人在寫(xiě)代碼時(shí),部分el-select加上了filterable屬性,部分沒(méi)有加上,導(dǎo)致部分下拉框可模糊匹配搜索,部分不可以。
- 正常來(lái)說(shuō),下拉框都要支持模糊匹配搜索的。
- 問(wèn)題不大,一個(gè)個(gè)加,可是手動(dòng)復(fù)制粘貼filterable屬性效率太低,能不能統(tǒng)一批量修改,批量添加filterable屬性呢?
答案是可以的。
解決方案一 使用vscode自帶的搜索工具,統(tǒng)一加filterable
簡(jiǎn)化一下,假設(shè)我有下面的目錄結(jié)構(gòu)。
添加圖片注釋?zhuān)怀^(guò) 140 字(可選)。
- 如上圖,我們需要把el-select組件,沒(méi)filterable的,加上。有的不用動(dòng)。
- 我們可以直接使用vscode自帶的文件搜索功能。
- 先把所有的filterable替換為空(filterable屬性,只有el-select組件用到了)。
- 再匹配到所有的el-select標(biāo)簽,再直接替換就完成任務(wù)了。
- 如下圖示操作。
第一步圖示:(filterable關(guān)鍵字替換為空,只針對(duì).vue文件操作)。
添加圖片注釋?zhuān)怀^(guò) 140 字(可選)。
第二步圖示:針對(duì).vue文件的el-select標(biāo)簽匹配替換(即為新加屬性)從而完成任務(wù)。
添加圖片注釋?zhuān)怀^(guò) 140 字(可選)。
解決方案二 使用node寫(xiě)一個(gè)腳本(重點(diǎn)),統(tǒng)一加filterable
通過(guò)上述圖示,我們發(fā)現(xiàn)vscode自帶的搜索匹配功能,也就是做了兩件事。
- 找到所有匹配的文件下的,目標(biāo)字符串。
- 然后進(jìn)行替換。
那我們是不是也可以使用node自己寫(xiě)對(duì)應(yīng)功能呢?答案是肯定的。
在此之前,我們先來(lái)回顧復(fù)習(xí)一下之前的相關(guān)知識(shí)。
知識(shí)點(diǎn)回顧一 使用正則統(tǒng)一替換字符串中的某個(gè)字符
我們寫(xiě)一個(gè)函數(shù),把字符串中的某些字符,替換成新的字符:
let str = `
白66依山盡,
黃河66入海流,
欲窮千66里目,
更上一層66樓
`
/**
* 一個(gè)用來(lái)在字符串中替換指定字符的函數(shù)
* @param {string} str 原來(lái)的字符串
* @param {string} targetStr 要替換的目標(biāo)字符
* @param {string} replaceStr 把目標(biāo)字符替換成什么字符
* @returns {string} 返回替換好的新的字符串
*/
function replaceAllStr(str, targetStr, replaceStr) {
// 把原來(lái)的字符串 通過(guò)正則 匹配到所有的目標(biāo)字符,統(tǒng)一替換成要替換的字符
return str.replace(new RegExp(targetStr, 'g'), replaceStr);
}
let newStr = replaceAllStr(str, '66', '88')
console.log('原來(lái)的字符串--->', str);
console.log('替換后的新字符串--->', newStr);
打印的效果圖如下:
添加圖片注釋?zhuān)怀^(guò) 140 字(可選)
知識(shí)點(diǎn)回顧二 本文用到的fs模塊的api
// 讀取對(duì)應(yīng)路徑下的目錄,返回?cái)?shù)組,數(shù)組中的每一項(xiàng)是文件夾名或文件名
fs.readdirSync(path)
// 讀取對(duì)應(yīng)路徑,獲取標(biāo)準(zhǔn)信息,并看看此路徑是文件還是文件夾
const stats = fs.statSync(path)
stats.isFile()
stats.isDirectory()
// 同步讀取文件內(nèi)容,讀取到的是文件中的所有字符串
fs.readFileSync(filePath, 'utf-8')
// 將數(shù)據(jù)內(nèi)容data同步寫(xiě)入到file文件中去
fs.writeFileSync(file, data)
知識(shí)點(diǎn)回顧三 本文用到的path模塊的api
// 獲取文件的后綴名
path.extname(file)
// 把文件夾和文件拼接成標(biāo)準(zhǔn)的路徑
path.join(folderPath, file);
欲知更多詳情如何,請(qǐng)?jiān)L問(wèn)nodejs中文網(wǎng):https://nodejs.cn/api/
知識(shí)點(diǎn)回顧四 遞歸讀取文件夾中的文件(可指定文件后綴)
根據(jù)上面的兩個(gè)知識(shí)點(diǎn)回顧,寫(xiě)一個(gè)遞歸讀取文件夾中的文件函數(shù),代碼如下:
const fs = require('fs');
const path = require('path');
function printAllFilesInFolder(folderPath, fileSuffix = '') {
const files = fs.readdirSync(folderPath); // 讀取對(duì)應(yīng)目錄【數(shù)組,文件夾或文件】
files.forEach((file) => { // 遍歷對(duì)應(yīng)目錄內(nèi)容
const filePath = path.join(folderPath, file); // 拼成標(biāo)準(zhǔn)路徑
const stats = fs.statSync(filePath); // fs模塊讀取此路徑得到文件信息狀態(tài)
if (stats.isFile() && path.extname(file) === fileSuffix) { // 若是文件且后綴名對(duì)得上
let fileStr = fs.readFileSync('./' + filePath, 'utf-8') // 就去讀取這個(gè)文件的內(nèi)容
console.log('--讀取到文件內(nèi)容為:-->', fileStr); // 最后再打印出來(lái)
} else if (stats.isDirectory()) { // 若是文件夾
printAllFilesInFolder(filePath, fileSuffix); // 文件夾就遞歸繼續(xù)操作
}
});
}
// 用法示例:傳入文件夾路徑來(lái)打印所有文件
const folderPath = './page';
const fileSuffix = '.vue';
printAllFilesInFolder(folderPath, fileSuffix);
最終腳本代碼
const fs = require('fs');
const path = require('path');
function replaceAllStr(str, targetStr, replaceStr) {
// 把原來(lái)的字符串 通過(guò)正則 匹配到所有的目標(biāo)字符,統(tǒng)一替換成要替換的字符
return str.replace(new RegExp(targetStr, 'g'), replaceStr);
}
function printAllFilesInFolder(folderPath, fileSuffix = '') {
const files = fs.readdirSync(folderPath); // 讀取對(duì)應(yīng)目錄【數(shù)組,文件夾或文件】
files.forEach((file) => { // 遍歷對(duì)應(yīng)目錄內(nèi)容
const filePath = path.join(folderPath, file); // 拼成標(biāo)準(zhǔn)路徑
const stats = fs.statSync(filePath); // fs模塊讀取此路徑得到文件信息狀態(tài)
if (stats.isFile() && path.extname(file) === fileSuffix) { // 若是文件且后綴名對(duì)得上
let fileStr = fs.readFileSync('./' + filePath, 'utf-8') // 就去讀取這個(gè)文件的內(nèi)容
/**
* 第一步,把文件中的filterable關(guān)鍵字字符串替換成空
* */
let newFileStr = replaceAllStr(fileStr, 'filterable', '')
/**
* 第二步,把文件中的el-select通過(guò)替換的方式加屬性filterable
* */
// let newFileStr = replaceAllStr(fileStr, '<el-select', '<el-select filterable ')
fs.writeFileSync(filePath, newFileStr) // 文件更新替換
} else if (stats.isDirectory()) { // 若是文件夾
printAllFilesInFolder(filePath, fileSuffix); // 文件夾就遞歸繼續(xù)操作
}
});
}
// 用法示例:傳入文件夾路徑來(lái)打印所有文件
const folderPath = './page';
const fileSuffix = '.vue';
printAllFilesInFolder(folderPath, fileSuffix);
gif效果演示圖
- 至此,我們的這個(gè)腳本,就有了vscode的搜索匹配功能的雛形了
- 也解決了自己的這個(gè)需求問(wèn)題《給幾百個(gè)el-select統(tǒng)一加filterable屬性》
為了方便大家使用,筆者把代碼推到了github上去了https://github.com/shuirongshuifu/efficiencyTool3。
Github倉(cāng)庫(kù)
總結(jié)
- 很多時(shí)候,當(dāng)我們使用一個(gè)工具,用的很順手的時(shí)候,空閑了,不妨想一想,這個(gè)工具的底層原理是啥,我自己能搞一個(gè)類(lèi)似的小工具demo嗎?
- 當(dāng)我們遇到一個(gè)問(wèn)題的時(shí)候,前期的知識(shí)儲(chǔ)備,決定了我們解決這個(gè)問(wèn)題的思路如何,或者沒(méi)思路。
- A bad pen is better than a good memory...