摘要:前情提要自動(dòng)工具,前端打字員的自我救贖記第一次發(fā)布包經(jīng)歷,是重構(gòu)中的代碼是版本可以工作的代碼配置文件待導(dǎo)入的模塊引用模塊的文件引用模塊的方式忽略的模塊實(shí)現(xiàn)監(jiān)聽(tīng)文件的刪除和添加以上代碼主要使用了來(lái)監(jiān)聽(tīng)文件的變化。
前情提要
自動(dòng) Import 工具,前端打字員的自我救贖
記第一次發(fā)布npm包經(jīng)歷,smart-import
GitHub:smart-import
develop是重構(gòu)中的代碼
master是1.0版本可以工作的代碼
配置文件from:待導(dǎo)入的模塊
to:引用模塊的文件
template:引用模塊的方式
ignored:忽略的模塊
{ "from": "demo/pages/**/*.vue", "to": "demo/router/index.js", "template": "const moduleName = () => import(modulePath)", "ignored": [ "demo/pages/pageA.vue" ] }實(shí)現(xiàn)監(jiān)聽(tīng)文件的刪除和添加
#!/usr/bin/env node const path = require("path") const chokidar = require("chokidar") const config = JSON.parse(fs.readFileSync("smart-import.json")) class SmartImport { constructor({ from }) { this.from = from this.extname = path.extname(from) } watch() { chokidar .watch(this.from, { ignoreInitial: true }) .on("add", file => { console.log("add", file) }) .on("unlink", file => { console.log("unlink", file) }) } } let smartImport = new SmartImport(config) smartImport.watch()
以上代碼主要使用了chokidar來(lái)監(jiān)聽(tīng)文件的變化。但存在一個(gè)問(wèn)題,如果刪除文件夾,而文件夾中包含匹配的模塊,不會(huì)觸發(fā)unlink事件。所以改成watch整個(gè)目錄,然后在add和unlink的回調(diào)中添加判斷文件后綴的代碼,因?yàn)槲覀兛赡苤辉谝?strong>.vue,而不在意.js
... watch() { chokidar .watch(path.dirname(this.from), { ignoreInitial: true }) .on("add", file => { if (path.extname(file) === this.extname) { console.log("add", file) } }) .on("unlink", file => { if (path.extname(file) === this.extname) { console.log("unlink", file) } }) } ...
現(xiàn)在符合from的文件的變動(dòng)(添加和刪除)都被監(jiān)視了,但是總覺(jué)得
if (path.extname(file) === this.extname) { }
寫了兩遍,不開(kāi)心
class SmartImport { constructor({ from }) { this.from = from this.extname = path.extname(from) this.checkExt = this.checkExt.bind(this) } watch() { const { from, checkExt } = this chokidar .watch(path.dirname(from), { ignoreInitial: true }) .on( "add", checkExt(file => { console.log("add", file) }) ) .on( "unlink", checkExt(file => { console.log("unlink", file) }) ) } checkExt(cb) { return file => { if (path.extname(file) === this.extname) { cb(file) } } } }
新添加了函數(shù)checkExt(),它的參數(shù)和返回值都是函數(shù),只是添加了判斷文件后綴名的邏輯。
高階函數(shù)有木有!
函數(shù)式編程有木有!
另外就是注意通過(guò)this.checkExt = this.checkExt.bind(this),綁定this的指向。
文件的變動(dòng)映射到數(shù)組中定義一個(gè)數(shù)組保存匹配的文件,另外匹配文件的變動(dòng)會(huì)觸發(fā)doImport()事件
代碼就變成了這樣
class SmartImport { constructor({ from, ignored }) { this.from = from this.ignored = ignored this.extname = path.extname(from) this.modules = [] } watch() { const { from, ignored, extname, modules } = this chokidar .watch(path.dirname(from), { ignoreInitial: true, ignored }) .on( "add", this.checkExt(file => { console.log("add", file) modules.push(file) this.doImport() }) ) .on( "unlink", this.checkExt(file => { console.log("unlink", file) _.remove(modules, p => p === file) this.doImport() }) ) } checkExt(cb) { const { extname } = this return file => { if (path.extname(file) === extname) { cb(file) } } } doImport() { console.log("doImport...") console.log(this.modules) } }
注意,我又把this.checkExt = this.checkExt.bind(this)給刪了,還是直接通過(guò)this.checkExt()調(diào)用方便,雖然代碼看起來(lái)凌亂了。
另外就是把this.doImport()又寫了兩遍。嗯,思考一下。其實(shí)modules變化,就應(yīng)該觸發(fā)doImport()。
發(fā)布-訂閱模式有木有
所以添加了個(gè)類ModuleEvent
class ModuleEvent { constructor() { this.modules = [] this.events = [] } on(event) { this.events.push(event) } emit(type, val) { if (type === "push") { this.modules[type](val) } else { _.remove(this.modules, p => p === val) } for (let i = 0; i < this.events.length; i++) { this.events[i].apply(this, [type, this.modules]) } } }
同時(shí)修改類SmartImport
class SmartImport { constructor({ from, ignored }) { this.from = from this.ignored = ignored this.extname = path.extname(from) this.moduleEvent = new ModuleEvent() } init() { this.moduleEvent.on((type, modules) => { this.doImport(type, modules) }) this.watch() } watch() { const { from, ignored, extname, modules } = this chokidar .watch(path.dirname(from), { ignoreInitial: true, ignored }) .on( "add", this.checkExt(file => { console.log("add", file) this.moduleEvent.emit("push", file) }) ) .on( "unlink", this.checkExt(file => { console.log("unlink", file) this.moduleEvent.emit("remove", file) }) ) } checkExt(cb) { const { extname } = this return file => { if (path.extname(file) === extname) { cb(file) } } } doImport(type, modules) { console.log(`type: ${type}`) console.log(modules) } } let smartImport = new SmartImport(config) smartImport.init()
終于理解了很多庫(kù)中on方法的原理有木有!對(duì)象中有個(gè)events,專門存這些回調(diào)函數(shù)有木有
另外我們觀察chokidar.on(eventType, cb),對(duì)比自己的moduleEvent.on(cb)。想想也是,也許我只想監(jiān)聽(tīng)特定的事件呢
修改ModuleEvent
class ModuleEvent { constructor({ from, ignored }) { this.modules = glob.sync(from, { ignore: ignored }) this.events = {} } on(type, cb) { if (!this.events[type]) { this.events[type] = [] } this.events[type].push(cb) } emit(type, val) { if (type === "push") { this.modules[type](val) } else { _.remove(this.modules, p => p === val) } for (let i = 0; i < this.events[type].length; i++) { this.events[type][i].apply(this, [this.modules]) } } }
后來(lái)覺(jué)得這個(gè)套路挺常見(jiàn),將其抽象出來(lái),最后形成代碼如下
#!/usr/bin/env node const fs = require("fs") const path = require("path") const glob = require("glob") const chokidar = require("chokidar") const _ = require("lodash") const config = JSON.parse(fs.readFileSync("smart-import.json")) const CustomEvent = (() => { let events = {} let on = (type, cb) => { if (!events[type]) { events[type] = [] } events[type].push(cb) } let emit = (type, data) => { for (let i = 0; i < events[type].length; i++) { events[type][i].apply(this, [data]) } } return { on, emit } })() class SmartImport { constructor({ from, ignored }) { this.from = from this.ignored = ignored this.extname = path.extname(from) this.modules = glob.sync(from, { ignore: ignored }) } init() { CustomEvent.on("push", m => { console.log("Do pushing") this.modules.push(m) }) CustomEvent.on("remove", m => { console.log("Do removing") _.remove(this.modules, p => p === m) }) this.watch() } watch() { const { from, ignored, extname, modules } = this chokidar .watch(path.dirname(from), { ignoreInitial: true, ignored }) .on( "add", this.checkExt(file => { CustomEvent.emit("push", file) }) ) .on( "unlink", this.checkExt(file => { CustomEvent.emit("remove", file) }) ) } checkExt(cb) { const { extname } = this return file => { if (path.extname(file) === extname) { cb(file) } } } } let smartImport = new SmartImport(config) smartImport.init()未完待續(xù)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92502.html
摘要:故事背景前情提要自動(dòng)工具,前端打字員的自我救贖的功能根據(jù)配置文件,在目標(biāo)文件中自動(dòng)導(dǎo)入規(guī)定目錄下自定義模塊,并監(jiān)聽(tīng)規(guī)定目錄下文件的變動(dòng),自動(dòng)更新尚在測(cè)試中的使用安裝工具編寫配置文件需要自動(dòng)導(dǎo)入的模塊的后綴名自動(dòng)導(dǎo)入的模塊的來(lái)源目 故事背景 前情提要:自動(dòng) Import 工具,前端打字員的自我救贖 github: smart-import smart-import 的功能 根據(jù)配置文件...
摘要:無(wú)論如何,單元測(cè)試一直是一中非常重要卻常常被忽視的技能。在實(shí)踐中,重構(gòu)的要求是很高的它需要有足夠詳盡的單元測(cè)試,需要有持續(xù)集成的環(huán)境,需要隨時(shí)隨地在小步伐地永遠(yuǎn)讓代碼處于可工作狀態(tài)下去進(jìn)行改善。 showImg(https://segmentfault.com/img/bVbttWF?w=1000&h=528); 五月初的時(shí)候朋友和我說(shuō)《重構(gòu)》出第 2 版了,我才興沖沖地下單,花了一個(gè)...
摘要:難以通過(guò)重構(gòu)手法完成設(shè)計(jì)的改動(dòng)先想像重構(gòu)的情況。何時(shí)不該重構(gòu)現(xiàn)有代碼根本不能正常運(yùn)作?,F(xiàn)在,我可以修改這個(gè)子類而不必承擔(dān)午一中影響另一處的風(fēng)險(xiǎn)。 重構(gòu):對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是再不改變軟件的可觀察行為的前提下,提高其可理解性,降低其修改成本。 兩頂帽子 添加新功能 添加新功能時(shí)不應(yīng)該修改既有代碼,只管添加新功能,通過(guò)測(cè)試重構(gòu) 重構(gòu)時(shí)你就不能再添加功能,只管改進(jìn)程序結(jié)構(gòu),此時(shí)...
摘要:改進(jìn)代碼設(shè)計(jì)的一個(gè)重要原則就是消除重復(fù)代碼使軟件更容易被理解優(yōu)秀的代碼能夠讓接收你代碼的付出更少的學(xué)習(xí)成本。重構(gòu)更容易找到重構(gòu)能加深對(duì)代碼的理解??梢灾貥?gòu)的情況添加功能時(shí)可以重構(gòu)。說(shuō)明你沒(méi)有發(fā)現(xiàn)代碼的錯(cuò)誤。需要重構(gòu)復(fù)審代碼時(shí)可以重構(gòu)。 為何重構(gòu) 重構(gòu)不是銀彈,但是幫助你達(dá)到以下幾個(gè)目的 改進(jìn)軟件設(shè)計(jì) 不良的程序需要更多的代碼。而代碼越多,正確的修改就越困難。改進(jìn)代碼設(shè)計(jì)的一個(gè)重要原則就...
摘要:重構(gòu)改善既有代碼設(shè)計(jì)動(dòng)詞使用一系列重構(gòu)手法,在不改變軟件可觀察行為的前提下,調(diào)整其結(jié)構(gòu)。修補(bǔ)錯(cuò)誤時(shí)重構(gòu)代碼時(shí)重構(gòu)怎么重構(gòu)關(guān)于代碼的重構(gòu)技巧參考重構(gòu)改善既有代碼設(shè)計(jì)讀書筆記代碼篇個(gè)人博客 重構(gòu)定義 名詞 對(duì)軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整,目的是在不改變軟件可觀察行為的前提下,提高其可理解性,降低其修改成本?!吨貥?gòu)-改善既有代碼設(shè)計(jì)》 動(dòng)詞 使用一系列重構(gòu)手法,在不改變軟件可觀察行為的前提下,...
閱讀 3050·2021-11-24 10:21
閱讀 1622·2021-10-11 10:57
閱讀 2838·2021-09-22 15:24
閱讀 2723·2021-09-22 14:58
閱讀 2355·2019-08-30 13:16
閱讀 3522·2019-08-29 13:05
閱讀 3442·2019-08-29 12:14
閱讀 3482·2019-08-27 10:55