您好,登錄后才能下訂單哦!
小編給大家分享一下Vue渲染的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
Vue 推薦在絕大多數情況下使用 template 來創建你的 HTML。但是模板畢竟是模板,不是真實的dom節點。從模板到真實dom節點還需要經過一些步驟
把模板編譯為render函數
實例進行掛載, 根據根節點render函數的調用,遞歸的生成虛擬dom
對比虛擬dom,渲染到真實dom
組件內部data發生變化,組件和子組件引用data作為props重新調用render函數,生成虛擬dom, 返回到步驟3
第一步: 模板到render
在我們使用Vue的組件化進行開發應用的時候, 如果仔細的查看我們要引入的組件, 例子如下
// App.vue <template> <div> hello word </div> </template> <script> export default { } </script> <style> </style>
在我們的主入口main.js
import Vue from 'vue' import App from './App' console.log(App) new Vue({ render: h => h(App) }).$mount('#app')
我們能夠看到在我們引入的App這個模塊,里面是一個對象,對象里面存在一個方法叫做render。在說render函數之前,我們可以想一想,每一次加載一個組件,然后對模板進行解析,解析完后,生成Dom,掛載到頁面上。這樣會導致效率很低效。而使用Vue-cli進行組件化開發,在我們引入組件的后,其實會有一個解析器(vue-loader
)對此模板進行了解析,生成了render函數。當然,如果沒有通過解析器解析為render函數,也沒有關系,在組件第一次掛載的時候,Vue會自己進行解析。源碼請參考: https://github.com/vuejs/vue/blob/dev/src/platforms/web/entry-runtime-with-compiler.js
這樣,能保證組件每次調用的都是render函數,使用render函數生成VNode。
第二步:虛擬節點VNode
我們把Vue的實例掛載到#app
, 會調用實例里面的render方法,生成虛擬DOM。來看看什么是虛擬節點,把例子修改一下。
new Vue({ render: h => { let root = h(App) console.log('root:', root) return root } }).$mount('#app')
上面生成的VNode就是虛擬節點,虛擬節點里面有一個屬性elm
, 這個屬性指向真實的DOM節點。因為VNode指向了真實的DOM節點,那么虛擬節點經過對比后,生成的DOM節點就可以直接進行替換。
這樣有什么好處呢?
一個組件對象,如果內部的data
發生變化,觸發了render函數,重新生成了VNode節點。那么就可以直接找到所對應的節點,然后直接替換。那么這個過程只會在本組件內發生,不會影響其他的組件。于是組件與組件是隔離的。
例子如下:
// main.js const root = new Vue({ data: { state: true }, mounted() { setTimeout(() => { console.log(this) this.state = false }, 1000) }, render: function(h) { const { state } = this // state 變化重新觸發render let root = h(App) console.log('root:', root) return root } }).$mount('#app')
// App.vue <script> export default { render: (h) => { let app = h('h2', ['hello world']) console.log('app:', app) return app } } </script>
我們可以看到,當main.js
中重新觸發render函數的時候,render方法里面有引用App.vue這個子組件。但是并沒有觸發App.vue組件的的render函數。
在一個組件內,什么情況會觸發render?
。
如何才能觸發組件的render
數據劫持是Vue的一大特色,原理官方已經講的很多了深入響應式原理。在我們給組件的data的屬性進行的賦值的時候(set),此屬性如果在組件內部初次渲染過程被引用(data的屬性被訪問,也就是數據劫持的get
), 包括生命周期方法或者render方法。于是會觸發組件的update(beforeUpdate -> render -> updated)。
注: 為了防止data被多次set從而觸發多次update, Vue把update存放到異步隊列中。這樣就能保證多次data的set只會觸發一次update。
當props會觸發組件的重新渲染是怎么發生的呢?
把父組件的data通過props傳遞給子組件的時候,子組件在初次渲染的時候生命周期或者render方法,有調用data相關的props的屬性, 這樣子組件也被添加到父組件的data的相關屬性依賴中,這樣父組件的data在set的時候,就相當于觸發自身和子組件的update。
例子如下:
// main.vue import Vue from 'vue' import App from './App' const root = new Vue({ data: { state: false }, mounted() { setTimeout(() => { this.state = true }, 1000) }, render: function(h) { const { state } = this // state 變化重新觸發render let root = h(App, { props: { status: state } }) console.log('root:', root) return root } }).$mount('#app') window.root = root
// App.vue <script> export default { props: { status: Boolean }, render: function (h){ const { status } = this let app = h('h2', ['hello world']) console.log('app:', app) return app } } </script>
截圖如下:
在main.js
中 state 狀態發生了變化,由false
=> true
, 觸發了自身與子組件的render方法。
補充
上面的內容是本人的一些使用心得,由于水平有限, 內容有些錯誤或者表達不當。多歡迎大神來指導!!!
PS:vue渲染過程的{{xxx}}顯示的解決辦法
這是由于瀏覽器的渲染機制導致的,瀏覽器是從頭到尾 如果你的js引用在底部,那么瀏覽器會先加載dom此時,你用于渲染的{{}}識別符,因為還沒讀到該識別符對應的js文件,所以會被解析為字符串而顯示在頁面中,我們可以用過自定義屬性v-cloak解決,
實例對象對應標簽中加入 v-cloak:
<div id="wrap" v-cloak>
然后在css中給定義屬性選擇器
[v-cloak]{ display:none }
vue實例創建完成后會把v-cloak去掉,在沒創建實例對象時,該標簽內的內容都會被隱藏
以上是“Vue渲染的示例分析”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。