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

資訊專欄INFORMATION COLUMN

VUE - MVVM - part4 - 優(yōu)化Watcher

CoffeX / 2372人閱讀

摘要:關(guān)于中的的實(shí)現(xiàn),差不多也就這樣了,當(dāng)然這僅僅是基礎(chǔ)的實(shí)現(xiàn),而且視圖層層渲染抽象成一個(gè)函數(shù)。不同于中的實(shí)現(xiàn),這里少了很多各種標(biāo)記和應(yīng)用標(biāo)記的過程。

看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。

回顧

首先我們思考一下截止當(dāng)前,我們都做了什么

通過 defineReactive 這個(gè)函數(shù),實(shí)現(xiàn)了對于數(shù)據(jù)取值和設(shè)置的監(jiān)聽

通過 Dep 類,實(shí)現(xiàn)了依賴的管理

通過 Watcher 類,抽象出了對象下某個(gè)屬性的依賴,以及屬性變換的 callBack

發(fā)現(xiàn)問題

對比 VueMVVM(先把視圖層的渲染抽象成一個(gè)函數(shù)),我們僅僅是實(shí)現(xiàn)了一些基礎(chǔ)性的東西。還有很大的區(qū)別,比如

我們的 Watcher 僅僅是抽象了對象下的單一屬性,而一般視圖層的渲染是涉及多個(gè)屬性的,而這些屬性的變化是同一個(gè)渲染函數(shù)(也就是 Vue 中編譯模板字符串最終生成的函數(shù))。

通過第一點(diǎn),我們可以得知,對象下的某幾個(gè)屬性是擁有同一個(gè) Watcher 的,換句話說就是,多個(gè) Dep 依賴與同一個(gè) Watcher,那么 Watcher 中該如何保存這些 Dep ,因?yàn)榘凑瘴覀兊膶?shí)現(xiàn),都一個(gè) Watcher 中僅僅保持一個(gè) Dep

解決問題 問題1

先讓我們想想,我們是如何把依賴注入到 Dep 中的

通過取值觸發(fā) defineProperty 中的 get,然后添加依賴

換句話說就是,我只要取過對應(yīng)屬性的值,那么就可以添加依賴。
看到之前 Watcher 的實(shí)現(xiàn):

this.get = function () {
    Dep.target = this
    let value = this.getter.call(object)
    Dep.target = null
    return value
}

這段代碼就實(shí)現(xiàn)了添加相應(yīng)屬性的依賴,歸根到底是這段起了作用

let value = this.obj[this.getter]

這里觸發(fā)了對應(yīng)屬性的 get ,那好針對第一個(gè)問題,我們只要在這里觸發(fā)多個(gè)屬性的 get 即可,至于要觸發(fā)那些屬性,我們交由調(diào)用者來控制,順理成章的這里應(yīng)該是一個(gè)函數(shù)??紤]之后便有了以下代碼

let Watcher = function (object, getter, callback) {
    this.obj = object
    // 這里的 getter 應(yīng)該是一個(gè)函數(shù)
    this.getter = getter
    this.cb = callback
    this.dep = null
    this.value = undefined

    this.get = function () {
        Dep.target = this
        // 將取值方式改成函數(shù)調(diào)用
        let value = this.getter.call(object)
        Dep.target = null
        return value
    }

    this.update = function () {
        const value = this.getter.call(object)
        const oldValue = this.value
        this.value = value
        this.cb.call(this.obj, value, oldValue)
    }

    this.addDep = function (dep) {
        this.dep = dep
    }

    this.value = this.get()
}
問題二

問題二其實(shí)很簡單,既然要保存多個(gè) dep 我們把保存的值聲明成一個(gè)數(shù)組即可

let Watcher = function (object, getter, callback) {
    this.obj = object
    this.getter = getter
    this.cb = callback
    // 聲明成數(shù)組
    this.deps = []
    this.value = undefined

    this.get = function () {
        Dep.target = this
        let value = this.getter.call(object)
        Dep.target = null
        return value
    }

    this.update = function () {
        const value = this.getter.call(object)
        const oldValue = this.value
        this.value = value
        this.cb.call(this.obj, value, oldValue)
    }

    this.addDep = function (dep) {
        // 將 dep 推入數(shù)組中
        this.deps.push(dep)
    }

    this.value = this.get()
}

為了方便取消這個(gè) Watcher ,我們在添加一個(gè)函數(shù),用于取消所有 DepWatcher 的依賴,所以最終 Watcher 的代碼如下:

let Watcher = function (object, getter, callback) {
    this.obj = object
    this.getter = getter
    this.cb = callback
    this.deps = []
    this.value = undefined

    this.get = function () {
        Dep.target = this
        let value = this.getter.call(object)
        Dep.target = null
        return value
    }

    this.update = function () {
        const value = this.getter.call(object)
        const oldValue = this.value
        this.value = value
        this.cb.call(this.obj, value, oldValue)
    }

    this.addDep = function (dep) {
        this.deps.push(dep)
    }

    // 新添加的取消依賴的方法
    this.teardown = function () {
        let i = this.deps.length
        while (i--) {
            this.deps[i].removeSub(this)
        }
        this.deps = []
    }

    this.value = this.get()
}
測試

我們僅僅優(yōu)化了 Watcher 的實(shí)現(xiàn),其他的代碼并沒有發(fā)生變化

let object = {}
defineReactive(object, "num1", 2)
defineReactive(object, "num2", 4)

let watcher = new Watcher(object, function () {
    return this.num1 + this.num2
}, function (newValue, oldValue) {
    console.log(`這是一個(gè)監(jiān)聽函數(shù),${object.num1} + ${object.num2} = ${newValue}`)
})

object.num1 = 3
// 這是一個(gè)監(jiān)聽函數(shù),3 + 4 = 7
object.num2 = 10
// 這是一個(gè)監(jiān)聽函數(shù),3 + 10 = 13

let watcher2 = new Watcher(object, function () {
    return this.num1 * this.num2
}, function (newValue, oldValue) {
    console.log(`這是一個(gè)監(jiān)聽函數(shù),${object.num1} * ${object.num2} = ${newValue}`)
})

object.num1 = 4
// 這是一個(gè)監(jiān)聽函數(shù),4 + 10 = 14
// 這是一個(gè)監(jiān)聽函數(shù),4 * 10 = 40
object.num2 = 11
// 這是一個(gè)監(jiān)聽函數(shù),4 + 11 = 15
// 這是一個(gè)監(jiān)聽函數(shù),4 * 11 = 44

// 測試取消
watcher2.teardown()

object.num1 = 5
// 這是一個(gè)監(jiān)聽函數(shù),5 + 11 = 16
object.num2 = 12
// 這是一個(gè)監(jiān)聽函數(shù),5 + 12 = 17

這就實(shí)現(xiàn)了對于多個(gè)屬性設(shè)置同一個(gè)監(jiān)聽,當(dāng)監(jiān)聽函數(shù)中的依賴屬性發(fā)生變化時(shí),自動執(zhí)行了相應(yīng)的函數(shù)。

關(guān)于 Vue 中的 MVVM 的實(shí)現(xiàn) ,差不多也就這樣了,當(dāng)然這僅僅是基礎(chǔ)的實(shí)現(xiàn),而且視圖層層渲染抽象成一個(gè)函數(shù)。

不同于 Vue 中的實(shí)現(xiàn),這里少了很多各種標(biāo)記和應(yīng)用標(biāo)記的過程。

這些會增加理解難度,之后有用到再說,實(shí)現(xiàn)完整的 MVVM 還需要對數(shù)組進(jìn)行特殊的處理,因?yàn)閿?shù)組是不能用 Object.defineProperty 來處理索引值的,這個(gè)也之后再說。

點(diǎn)擊查看相關(guān)代碼

系列文章地址

VUE - MVVM - part1 - defineProperty

VUE - MVVM - part2 - Dep

VUE - MVVM - part3 - Watcher

VUE - MVVM - part4 - 優(yōu)化Watcher

VUE - MVVM - part5 - Observe

VUE - MVVM - part6 - Array

VUE - MVVM - part7 - Event

VUE - MVVM - part8 - 優(yōu)化Event

VUE - MVVM - part9 - Vue

VUE - MVVM - part10 - Computed

VUE - MVVM - part11 - Extend

VUE - MVVM - part12 - props

VUE - MVVM - part13 - inject & 總結(jié)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/94210.html

相關(guān)文章

  • VUE - MVVM - part3 - Watcher

    摘要:解決第一個(gè)問題很簡單,我們把某個(gè)屬性的值對應(yīng)值變化時(shí)需要執(zhí)行的函數(shù)抽象成一個(gè)對象,然后把這個(gè)對象當(dāng)成是依賴,推入依賴管理中。的實(shí)現(xiàn)有了以上的考慮,那個(gè)依賴對象在中就是。新值作為添加的第一個(gè)函數(shù),很自豪。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 在 step2 中,我們實(shí)現(xiàn)了一個(gè)管理依賴的 Dep ,但是僅僅使用這個(gè)類并不能完成我們想實(shí)現(xiàn)的功能,而且代碼...

    wums 評論0 收藏0
  • VUE - MVVM - part5 - Observe

    摘要:具體代碼執(zhí)行方式進(jìn)入到的目錄下,命令行運(yùn)行即可。確保為一個(gè)對象如果對象下有則不需要再次生成函數(shù)返回該對象的實(shí)例,這里判斷了如果該對象下已經(jīng)有實(shí)例,則直接返回,不再去生產(chǎn)實(shí)例。這就確保了一個(gè)對象下的實(shí)例僅被實(shí)例化一次。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 回顧 在 step4 中,我們大致實(shí)現(xiàn)了一個(gè) MVVM 的框架,由3個(gè)部分組成: defineRe...

    xi4oh4o 評論0 收藏0
  • VUE - MVVM - part10 - Computed

    摘要:了解之后我們來實(shí)現(xiàn)它,同樣的為了方便理解我寫成了一個(gè)類這里的一般是的實(shí)例將屬性代理到實(shí)例下的構(gòu)造函數(shù)我們實(shí)現(xiàn)了代理屬性和更新計(jì)算屬性的值,同時(shí)依賴沒變化時(shí),也是不會觸發(fā)的更新,解決了以上的個(gè)問題。 看這篇之前,如果沒有看過之前的文章,移步拉到文章末尾查看之前的文章。 回顧 先捋一下,之前我們實(shí)現(xiàn)的 Vue 類,主要有一下的功能: 屬性和方法的代理 proxy 監(jiān)聽屬性 watche...

    callmewhy 評論0 收藏0
  • VUE - MVVM - part9 - Vue

    摘要:調(diào)用父類的方法類在我們上一步已經(jīng)實(shí)現(xiàn)。我們先實(shí)現(xiàn)的綁定,因?yàn)槭且槐O(jiān)聽,所以要進(jìn)行進(jìn)一步的處理。調(diào)用父類的方法方法綁定完事,其實(shí)就這么簡單。 看這篇之前,如果沒有看過之前的文章,可拉到文章末尾查看之前的文章。 前言 激動人心的時(shí)候即將來臨,之前我們做的 8 步,其實(shí)都在為這一步打基礎(chǔ),這一步,我們來簡單實(shí)現(xiàn)一個(gè) Vue 對象,還沒有看過之前代碼的同學(xué),請確認(rèn)看過之前的文章。 主要實(shí)現(xiàn)內(nèi)...

    yzd 評論0 收藏0
  • VUE - MVVM - part2 - Dep

    摘要:看這篇之前,如果沒看過先移步看實(shí)現(xiàn)中。同樣的,在取值時(shí)收集依賴,在設(shè)置值當(dāng)值發(fā)生變化時(shí)觸發(fā)依賴。中實(shí)現(xiàn)了一個(gè)的類來處理以上兩個(gè)問題,之后再說。以下語法下的,源碼中差不多就這樣點(diǎn)擊查看相關(guān)代碼系列文章地址優(yōu)化優(yōu)化總結(jié) 看這篇之前,如果沒看過 step1 先移步看 實(shí)現(xiàn) VUE 中 MVVM - step1 - defineProperty。 在上一篇我們大概實(shí)現(xiàn)了,Vue 中的依賴收集和...

    hover_lew 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<