成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

重構(gòu)smart-import

Pocher / 3192人閱讀

摘要:前情提要自動(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è)目錄,然后在addunlink的回調(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

相關(guān)文章

  • 記第一次發(fā)布npm包經(jīng)歷,smart-import

    摘要:故事背景前情提要自動(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ù)配置文件...

    Raaabbit 評(píng)論0 收藏0
  • 重構(gòu):一項(xiàng)常常被忽略的基本功

    摘要:無(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è)...

    idealcn 評(píng)論0 收藏0
  • 重構(gòu)改善既有的代碼設(shè)計(jì)(重構(gòu)原則)

    摘要:難以通過(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í)...

    XUI 評(píng)論0 收藏0
  • 重構(gòu)-改善既有代碼的設(shè)計(jì)(二) --重構(gòu)原則

    摘要:改進(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è)重要原則就...

    myshell 評(píng)論0 收藏0
  • 重構(gòu)-改善既有代碼設(shè)計(jì)》讀書筆記-重構(gòu)

    摘要:重構(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)手法,在不改變軟件可觀察行為的前提下,...

    ermaoL 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<