当前位置: 首页 > 后端技术 > Node.js

重构smart-import

时间:2023-04-03 14:06:13 Node.js

自动导入工具上一篇总结,前端打字员的自我救赎笔记首次发布npm包体验,smart-importGitHub:smart-importdevelop是重构大师1.0版本下的代码可以工作的代码配置文件:要导入的模块to:引用模块模板的文件:引用模块的方法ignored:被忽略的模块{"from":"demo/pages/**/*.vue","to":"demo/router/index.js","template":"constmoduleName=()=>import(modulePath)","ignored":["demo/pages/pageA.vue"]}实现监听文件的删除和添加#!/usr/bin/envnodeconstpath=require('path')constchokidar=require('chokidar')constconfig=JSON.parse(fs.readFileSync('smart-import.json'))classSmartImport{构造函数({from}){this.from=fromthis.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)})}}letsmartImport=newSmartImport(config)smartImport.watch()上面的代码主要是使用chokidar来监听文件变化,但是有个问题。如果删除一个文件夹,并且该文件夹包含匹配的模块,则不会触发取消链接事件。所以改成watch整个目录,然后在add和unlink的回调中加入判断文件后缀的代码,因为我们可能只关心.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)}})}...现在匹配thefilefrom的变化(增删改)被监听了,但是总觉得if(path.extname(file)===this.extname){}写了两遍,不开心classSmartImport{constructor({from}){this.from=fromthis.extname=path.extname(from)this.checkExt=this.checkExt.bind(this)}watch(){const{from,checkExt}=thischokidar.watch(path.dirname(from),{ignoreInitial:true}).on('add',checkExt(file=>{console.log('add',file)})).on('unlink',checkExt(file=>{console.log('unlink',file)}))}checkExt(cb){returnfile=>{if(path.extname(file)===this.extname){cb(file)}}}}新增函数checkExt(),它的参数和返回值都是函数,只是增加了判断文件扩展名的逻辑高阶函数。没有函数式编程!另外就是注意通过this.checkExt=this.checkExt.bind(this)绑定this的点。文件变化映射到一个数组定义一个数组来保存匹配文件,匹配文件变化会触发doImport()事件。代码变成这样classSmartImport{constructor({from,ignored}){this.from=fromthis.ignored=ignoredthis.extname=path.extname(from)this.modules=[]}watch(){const{from,ignored,extname,modules}=thischokidar.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{extna我}=这个返回文件=>{if(path.extname(file)===extname){cb(file)}}}doImport(){console.log('doImport...')console.log(this.modules)}}注意,我把this.checkExt=this.checkExt.bind(this)删掉了,直接通过this.checkExt()调用还是方便的,虽然代码看起来比较乱,this.doImport()写了两遍.好吧,考虑一下。事实上,当模块改变时,应该触发doImport()。发布-订阅模式有木有所以添加了一个类ModuleEventclassModuleEvent{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(leti=0;i{this.doImport(type,modules)})this.watch()}watch(){const{from,ignored,extname,modules}=thischokidar.watch(path.dirname(from),{ignoreInitial:true,忽略}).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}=thisreturnfile=>{if(path.extname(file)===extname){cb(file)}}}doImport(type,modules){console.log(`type:${type}`)console.log(modules)}}letsmartImport=newSmartImport(config)smartImport.init()终于明白了很多库中on方法的原理了!对象中有一个事件,专门存储了这些回调函数。此外,我们观察chokidar.on(eventType,cb)并与我们自己的moduleEvent.on(cb)进行比较想想也是,也许我只是想听听具体的事件?修改ModuleEventclassModuleEvent{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(leti=0;i{letevents={}leton=(type,cb)=>{如果(!events[type]){events[type]=[]}events[type].push(cb)}letemit=(type,data)=>{for(leti=0;i{console.log('Dopushing')this.modules.push(m)})CustomEvent.on('remove',m=>{console.log('Doremoving')_.remove(this.modules,p=>p===m)})this.watch()}watch(){const{from,ignored,extname,modules}=thischokidar.watch(path.dirname(from),{ignoreInitial:true,忽略}).on('add',this.checkExt(file=>{CustomEvent.emit('push',file)})).on('unlink',this.checkExt(file=>{CustomEvent.emit('remove',file)}))}checkExt(cb){const{extname}=这个返回文件=>{if(path.extname(file)===extname){cb(file)}}}}letsmartImport=newSmartImport(config)smartImport.init()未完成等待