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

資訊專欄INFORMATION COLUMN

VUE原理以及簡單實現(xiàn)

muddyway / 3312人閱讀

摘要:在原理中,最重要的部分就是如何實現(xiàn)數(shù)據(jù)的觀測,依賴的收集,視圖的更新。本文講的就是這三個的簡單實現(xiàn)。這樣做代碼似乎有點丑,我們在設(shè)置屬性觸發(fā)會發(fā)生函數(shù),有沒有一種更加智能的方式來實現(xiàn)通知變化呢。

在vue原理中,最重要的部分就是如何實現(xiàn)數(shù)據(jù)的觀測,依賴的收集,視圖的更新。本文講的就是Observer, Dep, Watcher這三個的簡單實現(xiàn)。
pub(publish)表示發(fā)布者,sub(subscribe)表示訂閱者, cb(callback)表示回調(diào)函數(shù)
如果你覺得這篇講的對你有所幫助,請幫我點個star

observer的實現(xiàn)

Observer的作用簡單來說就是讓object對象的屬性都用Object.defineProperty()來進行定義,這樣當獲取object的屬性,或者修改屬性的時候,就能夠觸發(fā)get,set達到數(shù)據(jù)的觀測的效果。

class Observer {
    constructor(value) {
        this.value = value 
        this.walk(this.value)
    }
    walk (value) {
        // 遞歸遍歷value的屬性
        Object.keys(value).forEach((key) = > {
            defineReactive(value, key, value[key])
        })
    }
}
function defineReactive(obj, key ,val) {
    let childOb = observe(val)
    Obeject.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            console.log("")
            return val
        },
        set(newVal) {
            console.log("")
            val = newVal
            childOb = observe(val)
        }
    })
}
function observe (value) {
    if (typeof value === "object" && !Array.isArray(value)) {
        value = new Observer(value)
    }
}

defineReactive的作用就是給對象的屬性進行簡單的數(shù)據(jù)觀測,一旦值獲取或者設(shè)置就會觸發(fā)一些行為.因為一個對象的屬性可能還是對象,所以在這里我們添加observe函數(shù)來遍歷值,讓一個對象的屬性的屬性還是可以進行觀測的,簡單呢來說的意思就是讓所有屬性都可以進行忽略。當然在實際情況中,我們還需要考慮數(shù)組的情況,但都大同小異。
這樣做代碼似乎有點丑,我們在設(shè)置屬性觸發(fā)set會發(fā)生console.log()函數(shù),有沒有一種更加智能的方式來實現(xiàn)通知變化呢。這里我們就需要用消息訂閱器來進行實現(xiàn),這樣做我們就不需要通過觀察console.log()輸出的值來看進行的情況,我們只需要在set方法里邊加一個通知,一旦值發(fā)生變化,就通知外邊值發(fā)生了改變

Dep的實現(xiàn):

Dep的作用就是用來收集屬性值的變化,一旦set方法觸發(fā)的時候,就更新視圖。那就準備一個數(shù)組來進行收集吧!
下面是Dep的實現(xiàn):

class Dep {
    constructor() {
        this.subs = []
    }
    addSub (sub) {
        this.subs.push(sub)
    }
    notify () {
        const subs = this.subs.slice()
        subs.forEach((sub) => {
            sub.update() // 視圖更新
        })
    }
}

上面就是Dep的簡單實現(xiàn),addSub的作用是增加訂閱者,因為有很多訂閱者,我們需要用一個數(shù)組將它進行存儲,notify()函數(shù)的作用就是當set發(fā)生的時候,進行通知,update()這個函數(shù)待會在watcher中會講到。實現(xiàn)了Dep我們是不是該更改了set()函數(shù)了呢,下面是defineReactive()修改后的代碼

function defineReactive(obj, key ,val) {
    let dep = new Dep() // 畢竟要使用Dep的方法
    let childOb = observe(val)
    Obeject.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            return val
        },
        set(newVal) {
            val = newVal
            childOb = observe(val)
            dep.notify() // 因為數(shù)據(jù)改變了,我們就通知Dep
        }
    })
}

一旦觸發(fā)set,就調(diào)用dep.notify(),notify的作用就是針對訂閱者遍歷進行更新。

Watcher的簡單實現(xiàn):

watcher的作用,就是當狀態(tài)發(fā)生改變的時候,更新視圖,我們可以假設(shè)

class Watcher {
    constructor (vm, cb, expOrFn) {
        this.vm = vm // 這表示一個Vue的實例
        this.cb = cb
        // 這里需要考慮expOrFn是字符串或者函數(shù)的情況
        // 這里做一個簡化,只考慮函數(shù)的情況
        this.getter = expOrFn
        this.value = this.get()
    }
    get () {
        Dep.target = this 
        const vm = this.vm
        value = this.getter.call(this.vm, vm)
        Dep.target = null
        return value 
    }
    update () {
        this.run()
    }
    run () {
        const value = this.get()
        if (value !== this.value) {
            const oldValue = this.value
            this.value = value
            this.cb.call(this.vm, value, oldValue) 
        }
    }
}

Watcher的簡單實現(xiàn)就完成了,在Dep()構(gòu)造函數(shù)中,我們使用了sub.update()這行代碼,而update函數(shù)是Watcher里邊的方法,說明每一個sub都是Wathcer的實例,問題是我們應(yīng)該如何通過addSub()這個方法,將Watcher加入到subs這個數(shù)組中盡心存儲呢,答案還是在defineReactive()里邊進行修改

function defineReactive(obj, key ,val) {
    let dep = new Dep() // 畢竟要使用Dep的方法
    let childOb = observe(val)
    Obeject.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get() {
            if(Dep.target) {
                dep.addSub(Dep.target)
            }
            return val
        },
        set(newVal) {
            val = newVal
            childOb = observe(val)
            dep.notify() // 因為數(shù)據(jù)改變了,我們就通知Dep
        }
    })
}

這樣是不是就實現(xiàn)了往Dep里邊加Watcher了,vue源碼中比這個復(fù)雜的多,各種參數(shù),看著頭大。本文的宗旨就是通過簡化讓你了解內(nèi)部原理,如果需要更深入了解就需要閱讀源碼了。

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

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

相關(guān)文章

  • 前端路由簡介以及vue-router實現(xiàn)原理

    摘要:后端路由簡介路由這個概念最先是后端出現(xiàn)的。前端路由模式隨著的流行,異步數(shù)據(jù)請求交互運行在不刷新瀏覽器的情況下進行。通過這些就能用另一種方式來實現(xiàn)前端路由了,但原理都是跟實現(xiàn)相同的。 后端路由簡介 路由這個概念最先是后端出現(xiàn)的。在以前用模板引擎開發(fā)頁面時,經(jīng)常會看到這樣 http://www.xxx.com/login 大致流程可以看成這樣: 瀏覽器發(fā)出請求 服務(wù)器監(jiān)聽到80端口(或4...

    tuomao 評論0 收藏0
  • 前端面試題大集合:來自真實大廠的532道面試題(只有題,沒有答案)

    答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@??途W(wǎng)發(fā)布的真實大廠前端面經(jīng)題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復(fù),但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統(tǒng)學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...

    Kerr1Gan 評論0 收藏0
  • 前端面試題大集合:來自真實大廠的532道面試題(只有題,沒有答案)

    答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@??途W(wǎng)發(fā)布的真實大廠前端面經(jīng)題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復(fù),但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統(tǒng)學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...

    lushan 評論0 收藏0
  • 前端面試題大集合:來自真實大廠的532道面試題(只有題,沒有答案)

    答案自己谷歌或百度找。 一、來源背景 面試題是來自微博@??途W(wǎng)發(fā)布的真實大廠前端面經(jīng)題目,我一直在收集題目長期一個一個的記錄下來的,可能會有重復(fù),但基本前端的面試大綱和需要掌握的知識都在其中了,面試題僅做學習參考,學習者閱后也要用心鉆研其中的原理,重要知識需要系統(tǒng)學習、透徹學習,形成自己的知識鏈。 二、532道前端真實大廠面試題 express和koa的對比,兩者中間件的原理,koa捕獲異常多種情...

    joyvw 評論0 收藏0
  • Vue面試題精選:Vue原理以及雙向數(shù)據(jù)綁定的實戰(zhàn)過程

    摘要:雙向數(shù)據(jù)綁定指的是,將對象屬性變化與視圖的變化相互綁定。數(shù)據(jù)雙向綁定已經(jīng)了解到是通過數(shù)據(jù)劫持的方式來做數(shù)據(jù)綁定的,其中最核心的方法便是通過來實現(xiàn)對屬性的劫持,達到監(jiān)聽數(shù)據(jù)變動的目的。和允許觀察數(shù)據(jù)的更改并觸發(fā)更新。 1 MVVM 雙向數(shù)據(jù)綁定指的是,將對象屬性變化與視圖的變化相互綁定。換句話說,如果有一個擁有name屬性的user對象,與元素的內(nèi)容綁定,當給user.name賦予一個新...

    malakashi 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<