最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue模擬響應(yīng)式原理底層代碼實(shí)現(xiàn)的示例

 更新時(shí)間:2021年08月16日 09:40:47   作者:メSerendipity  
最近去面試的人都會有這個(gè)體會,去年面試官只問我怎么用vue,今年開始問我vue響應(yīng)式原理,本文就詳細(xì)的介紹一下

整體分析Vue的基本結(jié)構(gòu)如下圖所示:(備注:完整代碼github地址https://github.com/1512955040/MiniVue


上圖中,為我們模擬最小vue的整體結(jié)構(gòu),首先創(chuàng)建一個(gè)vue類型,它負(fù)責(zé)把data中的成員注入到vue實(shí)例中,并且轉(zhuǎn)化成getter/setter,observer的作用是數(shù)據(jù)劫持,對data中的屬性進(jìn)行數(shù)據(jù)監(jiān)聽,如果數(shù)據(jù)發(fā)生變化會獲取到最新的值,并通知dep。Compiler的作用是解析每個(gè)元素中的指令和差值表達(dá)式并替換成相應(yīng)的數(shù)據(jù)。Dep的作用是添加觀察者,當(dāng)數(shù)據(jù)發(fā)生變化時(shí)通知所有的觀察者。Watcher內(nèi)部有一個(gè)Update方法負(fù)責(zé)更新視圖,下面我們用代碼的方式一一進(jìn)行實(shí)現(xiàn)。

1.Vue.js功能:

1-1負(fù)責(zé)接收初始化的參數(shù)(選項(xiàng))

1-2負(fù)責(zé)把data中的屬性注入到vue實(shí)例,轉(zhuǎn)化成getter/setter

1-3負(fù)責(zé)調(diào)用observer監(jiān)聽data中所有屬性的變化

1-4負(fù)責(zé)調(diào)用Compiler解析指令/差值表達(dá)式

類圖結(jié)構(gòu)如下:

如上圖所示:vue類中有三個(gè)屬性,分別是$options,$el,$data,這三個(gè)屬性記錄構(gòu)造函數(shù)中傳過來的參數(shù)。_proxyData為vue類中的方法

所以以_開頭的成員就是私有成員,這個(gè)方法的功能是把data中的屬性轉(zhuǎn)化為getter和setter注入到vue實(shí)例中。

class Vue{
    constructor(options) {
        //1.通過屬性保存選項(xiàng)中的數(shù)據(jù)
        this.$options = options || {}
        this.$data = options.data || {}
        this.$el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el
        //2.把data中的成員轉(zhuǎn)化為getter和setter,注入到vue實(shí)例中
        this._proxyData(this.$data)
        //3.調(diào)用observer對象,監(jiān)聽數(shù)據(jù)的變化
        new Observer(this.$data)
        //4.調(diào)用compiler對象,解析指令和差值表達(dá)式
        new Compiler(this)
    }
    //把Vue的屬性轉(zhuǎn)化為getter和setter,注入到Vue實(shí)例中
    _proxyData(data){
        //遍歷data中所有屬性
        Object.keys(data).forEach(key=>{
          //把data的屬性注入到vue實(shí)例全局中
          Object.defineProperty(this,key,{
              enumerable:true,
              configurable:true,
              get(){
                return data[key]
              },
              set(newValue){
                if(newValue===data[key]){
                    return 
                }
                data[key]=newValue
             }
        })    
      })
    }
}

2.Observer.js功能(數(shù)據(jù)劫持):

2-1 負(fù)責(zé)把data選項(xiàng)中的屬性轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)

2-2 data中的某個(gè)屬性也是對象,把該屬性轉(zhuǎn)化為響應(yīng)式數(shù)據(jù)

2-3 數(shù)據(jù)變化發(fā)送通知

類圖結(jié)構(gòu)如下:

如上圖所示:

walk方法的作用是遍歷data中的所有屬性,defineReactive是定義響應(yīng)式數(shù)據(jù),也就是通過調(diào)用defineReactive方法把屬性轉(zhuǎn)化為getter和setter。

class Observer{
    constructor(data) {
        this.walk(data)
    }
    //walk方法遍歷data中的所有屬性
    walk(data) {
        //1.判斷data是否對象
        if(!data || typeof data !=='object'){
            return 
        }
        //2.遍歷data對象的所有屬性
        Object.keys(data).forEach(key=>{
            this.defineReactive(data,key,data[key])
        })
    }
    //degineReactivce方法定義響應(yīng)式數(shù)據(jù) 把屬性轉(zhuǎn)化為getter和setter
    defineReactive(obj,key,val) {
        let that=this
        // 負(fù)責(zé)收集依賴,并發(fā)送通知
        let dep=new Dep()
        //如果val傳入對象的話也給對象里面的屬性添加getter和setter方法
        this.walk(val)
        Object.defineProperty(obj,key,{
            enumerable:true,
            configurable:true,
            get(){
                // 收集依賴
                Dep.target && dep.addSub(Dep.target)
                return val
            },
            set(newValue){
                if(newValue==val){
                    return 
                }
                val=newValue
                //如果給屬性重新賦值成對象,給對象里面的屬性重新添加getter和setter方法
                //比如:歷史數(shù)據(jù)vm.msg="Hello World" 修改之后vm.msg={a:'Hwllo World'}
                //再次調(diào)用此方法給vm.msg.a重新添加getter和setter方法
                that.walk(newValue)
                //發(fā)送通知
                dep.notify()
            }
        })
    }
}

3.Compiler.js功能:

3-1 負(fù)責(zé)編譯模板,解析指令/差值表達(dá)式

3-2 負(fù)責(zé)頁面的首次渲染

3-3 當(dāng)數(shù)據(jù)變化后重新渲染視圖

類圖結(jié)構(gòu)如下:

如上圖所示:

el為構(gòu)造函數(shù)傳過來的options.el,vm是vue的實(shí)例,下面都是vm的方法,對DOM進(jìn)行操作。compile方法內(nèi)部遍歷dom對象的所有節(jié)點(diǎn),并且

判斷這些節(jié)點(diǎn)是文本節(jié)點(diǎn),如果是文本節(jié)點(diǎn)解析差值表達(dá)式,如果是元素節(jié)點(diǎn)解析指令,isTextNode和isElementNode方法判斷是文本節(jié)點(diǎn)還

是元素節(jié)點(diǎn)。compileElement和compileText方法解析差值表達(dá)式和指令。isDirective這個(gè)方法判斷元素屬性是否是指令。

4.Dep.js功能:

4-1 收集依賴,添加觀察者(watcher)

4-2 通知所有觀察者

如上圖所示:

在vue的響應(yīng)式機(jī)制中,使用觀察者模式來響應(yīng)數(shù)據(jù)的變化,Dep的作用是收集依賴,在getter方法中收集依賴,在setter方法中通知依賴,每

一個(gè)響應(yīng)式的屬性都會場景一個(gè)Dep對象,負(fù)責(zé)收集所有依賴于該屬性的地方,所有依賴于該屬性的位置都會創(chuàng)建一個(gè)watcher對象,所以

Dep就是收集于該屬性的watcher對象,使用setter方法去通知依賴,當(dāng)屬性發(fā)生變化時(shí)調(diào)用nodify方法去發(fā)送通知,然后調(diào)用watcher對象

的update方法。

類的機(jī)構(gòu)如下圖:

如上圖所示:

subs是一個(gè)數(shù)組,存儲dep中所有的watcher,addSub方法添加watcher,notify方法發(fā)布通知

class Dep{
    constructor() {
        //存儲所有的觀察者
        this.subs=[]
    }
    // 添加觀察者
    addSub(sub){
        if(sub && sub.update) {
            this.subs.push(sub)
        }
    }
    //發(fā)送通知
    notify(){
        this.subs.forEach(sub =>{
            sub.update()
        })
    }
}

5.Watcher.js功能:

5-1 當(dāng)數(shù)據(jù)變化觸發(fā)依賴,dep通知所有的Watcher實(shí)例更新視圖

5-2 自身實(shí)例化的時(shí)候往dep對象中添加自己

如上圖所示:

data中的每一個(gè)屬性都要創(chuàng)建一個(gè)Dep對象, 在收集依賴的時(shí)候把所有對象的watcher添加到dep對象的subs數(shù)組中,在setter對象中發(fā)送通

知,調(diào)用Dep對象的notify方法通知所有關(guān)聯(lián)的watcher對象更新視圖。

類圖結(jié)構(gòu)如下:

如上圖所示:

update對象更新視圖,cb回調(diào)函數(shù),指明如何更新視圖。在更新視圖的時(shí)候需要一個(gè)屬性key(data中的屬性名稱),oldvalue是key 對應(yīng)的值。

class Watcher{
    constructor(vm,key,cb) {
        this.vm=vm
        //data中的屬性名稱
        this.key=key
        //回調(diào)函數(shù)負(fù)責(zé)更新視圖
        this.cb=cb
        //把watcher對象記錄到Dep類的靜態(tài)屬性target
        Dep.target =this
        //觸發(fā)get方法,在get方法中會調(diào)用addSub
        this.oldValue=vm[key]
        Dep.target=null
    }
    //當(dāng)數(shù)據(jù)發(fā)生變化時(shí)更新視圖
    update(){
        let newValue=this.vm[this.key]
        if(this.oldValue === newValue){
            return
        }
        this.cb(newValue)
    }
}

下面通過這張圖作整體流程的總結(jié):

到此這篇關(guān)于Vue模擬響應(yīng)式原理底層代碼實(shí)現(xiàn)的示例的文章就介紹到這了,更多相關(guān)Vue 響應(yīng)式原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue實(shí)現(xiàn)標(biāo)簽頁切換/制作tab組件詳細(xì)教程

    vue實(shí)現(xiàn)標(biāo)簽頁切換/制作tab組件詳細(xì)教程

    在項(xiàng)目開發(fā)中需要使用vue實(shí)現(xiàn)tab頁簽切換功能,所以這里總結(jié)下,這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)標(biāo)簽頁切換/制作tab組件的相關(guān)資料,需要的朋友可以參考下
    2023-11-11
  • 深入淺析Vue中mixin和extend的區(qū)別和使用場景

    深入淺析Vue中mixin和extend的區(qū)別和使用場景

    Vue中有兩個(gè)較為高級的靜態(tài)方法mixin和extend,接下來給大家介紹Vue中mixin和extend的區(qū)別和使用場景,感興趣的朋友一起看看吧
    2019-08-08
  • Vue中常用的rules校驗(yàn)規(guī)則的實(shí)現(xiàn)

    Vue中常用的rules校驗(yàn)規(guī)則的實(shí)現(xiàn)

    在vue開發(fā)中,難免遇到各種表單校驗(yàn),本文主要介紹了Vue中常用的rules校驗(yàn)規(guī)則的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • element?table?數(shù)據(jù)量大頁面卡頓的解決

    element?table?數(shù)據(jù)量大頁面卡頓的解決

    這篇文章主要介紹了element?table?數(shù)據(jù)量大頁面卡頓的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 簡化vuex的狀態(tài)管理方案的方法

    簡化vuex的狀態(tài)管理方案的方法

    在 vuejs 相關(guān)項(xiàng)目開發(fā)過程中,我們常常會使用 vuex 作為狀態(tài)管理工具, 整個(gè)組件的狀態(tài)做為單向數(shù)據(jù)流的模式管理,這篇文章主要介紹了簡化vuex的狀態(tài)管理方案的方法,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 如何解決模塊““vue“”沒有導(dǎo)出的成員“ref”問題

    如何解決模塊““vue“”沒有導(dǎo)出的成員“ref”問題

    這篇文章主要介紹了如何解決模塊““vue“”沒有導(dǎo)出的成員“ref”問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Vue仿支付寶支付功能

    Vue仿支付寶支付功能

    這篇文章主要介紹了Vue仿支付寶支付功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-05-05
  • Vite打包時(shí)去除console的方法實(shí)現(xiàn)

    Vite打包時(shí)去除console的方法實(shí)現(xiàn)

    Vite打包項(xiàng)目時(shí),需要去除開發(fā)時(shí)加入的console、debugger調(diào)試信息,本文主要介紹了Vite打包時(shí)去除console的方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • 解決vuex數(shù)據(jù)丟失問題

    解決vuex數(shù)據(jù)丟失問題

    本文主要介紹了解決vuex?數(shù)據(jù)丟失問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Vue Router4 嵌套路由的示例代碼

    Vue Router4 嵌套路由的示例代碼

    在 Vue Router 4 中,嵌套路由是一種非常重要的功能,它允許我們創(chuàng)建更復(fù)雜的 UI 結(jié)構(gòu),同時(shí)保持路由的清晰和易于管理,這篇文章主要介紹了Vue Router4 嵌套路由,需要的朋友可以參考下
    2024-04-04

最新評論

清原| 兰州市| 龙胜| 郧西县| 丘北县| 泾源县| 沂源县| 崇文区| 曲沃县| 临洮县| 平和县| 永靖县| 东阳市| 汉源县| 盘山县| 孟村| 焦作市| 化德县| 尉氏县| 临西县| 陆川县| 嘉荫县| 高安市| 财经| 博客| 定兴县| 乐都县| 寿宁县| 青州市| 迁安市| 红桥区| 永新县| 伊金霍洛旗| 阳原县| 通渭县| 清远市| 阜平县| 鹤庆县| 通州市| 张家界市| 元谋县|