vue入門:(底層渲染實現render函數、實例生命周期)


  • vue實例渲染的底層實現
  • vue實例生命周期
  • vue實例渲染的生命周期與鈎子函數詳解

 一、vue實例渲染的底層實現

 1.1實例掛載

在vue中實例掛載有兩種方法:第一種在實例化vue時以el屬性實現,第二種是通過vue.$mount()方法實現掛載。不管是哪種掛載都不影響vue實例化組件的執行流程和模式,只是通過vue.$mount()方法實現掛載可以更靈活的實現組件復用和掛載。

var vm = new Vue({
    el:'掛載元素id',//實例化el屬性實現掛載
    ...
})
var vm1 = new Vue({...});
vm1.mount('掛載元素id');//vue.mount()方法實現掛載
//參數模型:# + id

1.2構建DOM抽象語法樹與template

在vue實例化中有一個非常關鍵的操作就是構建DOM抽象語法樹,基於抽象語法樹生成虛擬節點,然后再將數據渲染到虛擬節點上,再將完成數據渲染的節點添加到document中刷新頁面,呈現頁面效果。構建抽象語法樹有三種方式:1.基於綁定的實例化屬性el和$mount()方法構建;2.基於實例化屬性template添加的模板構建;3.基於ready()的參數構建。

這三種構建方式的優先級:render() > template > el

本質上的el與template與render()函數的參數都是一個原理,通過el就是將el指向的元素的DOM模型的outerHTML屬性值拿到,outerHTML屬性值與template的形式完全一樣就是html文本的字符串形式;然后將這個字符串形式的html文本轉換成js對象模型,render()函數中使用的就直接是js對象模型,接着通過js對象模型所表達的html結構轉換成AST(抽象語法樹)用於構建虛擬節點VNode;render()函數再在這個虛擬節點上渲染數據,完成數據渲染后就添加到html文檔中渲染到頁面。

通過元素在window上的id指向獲取到id匹配的元素節點對象的outerHTML屬性值:

<div id="app">我是一個div</div>
<script>
     console.log(app.outerHTML);//"<div id="app">我是一div</div>"
 </script>

通過vue對象實例化屬性template構建vue實例:

<div id="app">我是一個div</div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>我是template模板構建的節點</div>`
    })
</script>

通過vue實例化將實例化對象屬性template的模板替代app指向的原節點,實質上是在vue實例構建過程中如果發現有template就不會再去獲取掛載節點的結構了。接着再來看看render()方法如何實現vue實例構建:

<div id="app">我是一個div</div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>我是template模板構建的節點</div>`,
        render(createElement){
            return createElement("p");
        }
    })
</script>

通過添加render()方法刷新頁面會發現頁面變成了空白,也就是說el掛載原節點和template模板構建的節點都沒生效,查看瀏覽器控制台可以看到在原app指向的節點的位置被一個空的p標簽替代了。這就是說render()函數的優先級大於template和el,但是要注意的是vue實例化必須是在通過el或者vue.mount()掛載才會去執行render()節點渲染方法,不然一個不掛載的vue實例有何必要渲染呢?

1.3基於JS對象模型的AST抽象語法樹構建及虛擬節點渲染:

render(createElement){
    return createElement(ElementName,ElementProperty,ChildNode);
}

這里不深入討論render的設計實現,也不討論虛擬節點的具體底層實現原理,也不深入探究render的復雜應用,僅僅對render()函數基於js對象模型構建AST抽象語法樹做出解析。

createElement:聲明工具函數的名稱;

ElementName:設定抽象語法樹根節點元素名稱;

ElementProperty:設定根節點元素的屬性;

ChildNode:設定子節點;

render(createElement){
    return createElement("p",{
        style:{
            color:"red",
            fontSize:'18px'
        },
        class:['classname1','classname2']
    },"我是由render構建的p標簽");
}

基於data的構建方式:

<div id="app">我是一個div</div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>我是template模板構建的節點</div>`,
        data:{
            classname1:true,
            classname2:false,
            text:'我時由render構建的p標簽'
        },
        render(createElement){
            return createElement("p",{
                style:{
                    color:"red",
                    fontSize:'18px'
                },
                class:{//基於數據綁定class
                    classname1:this.classname1,
                    classname2:this.classname2
                }
            },this.text);
        }
    })
</script>

使用createElement工具方法迭代子節點(在前面的子節點都直接使用字符串,就是說明其是文本節點,使用createElement可以創建元素子節點):

<div id="app">我是一個div</div>
<script>
    var vm = new Vue({
        el:"#app",
        template:`<div>我是template模板構建的節點</div>`,
        data:{
            classname1:true,
            classname2:false,
            text:'我時由render構建的p標簽'
        },
        render(createElement){
            return createElement("p",{
                style:{
                    color:"red",
                    fontSize:'18px'
                },
                class:{//基於數據綁定class
                    classname1:this.classname1,
                    classname2:this.classname2
                }
            },[
                '我是一個文本節點',
                createElement('h1','我是h1標簽'),
                createElement('h2',{
                    style:{
                        color:'orange'
                    }
                },'我是h2標簽')
            ]);
        }
    })
</script>

其實本質上render()函數與頁面渲染中的抽象語法樹構建是異曲同工,一個是基於js對象參數構建,一個是通過html文檔構建;一個是在js中完成一個是在瀏覽器底層渲染模型中完成。

 二、vue實例生命周期與鈎子函數

 

更多的鈎子函數相關內容可以參考這篇博客: https://www.jianshu.com/p/3e91a1c42397

 三、vue實例渲染的生命周期與鈎子函數詳解

Vue 渲染底層原理之render函數·Vue 實例生命周期與鈎子函數   ______________________________________________________________________________    
|       Init Events & Lisfecyde:初始化創建vue實例需要的相關事件與實例化生命周
|       期需要的函數。
|    
|____①___beforeCreate():初始化vue實例之前執行的鈎子函數。
|        
|        Init injections & reactivity:初始化實例,將實例參數:el、data、methods等
|        添加到實例對象上,為構建虛擬DOM做好准備。
|        |____②___created():初始化vue實例之后執行的鈎子函數。
||    建    el、$mount(el):判斷實例是通過哪種掛載方法。
|    抽    判斷是否采用template模板,還是通過元素的outerHTML屬性構建抽象語法
|    象    樹。(所以在這之前需要判斷是通過哪種方式掛載,如果沒有模板就需要基於
|    語    掛載的node結構來構建抽象語法樹)
|||____③___beforeMount():渲染頁面之前執行的鈎子函數。
|        
|        Create vm.$el and replace “el” with it:基於抽象語法樹與數據構建虛擬node,
|        並將虛擬node渲染到頁面,形成HTML文檔,如果之前在HTML中包含定義
|        結構的元素(包含自定義元素)會被替換。(渲染頁面包含三個步驟:構建虛
|        擬節點、刪除原文節點、插入新的文件節點)
|        
|____④___mounted():渲染頁面之后執行的鈎子函數。
|        
|________________________________________________________________________                                                                        
|                                                                         |
|____⑤___beforeUpdate():重新渲染之前觸發的鈎子函數。                         |
|                                                                         |
|                        Mounted(觸發重新渲染—數據迭代更新)                  |
|                                                                         |
|____⑥___update():重新渲染之后觸發的渲染函數。                               |
|                                                                         ||_________________________________________________________________________|                                                                          |
|        
|____⑦___beforeDestroy():實例銷毀前觸發的鈎子函數。
|        
|        Teardown watchers, child components and event listeners:拆卸監
|        視器、子組件和事件偵聽器。)
|        Destroy【銷毀實例】
|        
|____⑧___destroyed():實例銷毀后執行的鈎子函數。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM