Vue 推薦在絕大多數狀況下使用 template 來建立你的 HTML。可是模板畢竟是模板,不是真實的dom節點。從模板到真實dom節點還須要通過一些步驟html
在咱們使用Vue的組件化進行開發應用的時候, 若是仔細的查看咱們要引入的組件, 例子以下vue
// App.vue <template> <div> hello word </div> </template> <script> export default { } </script> <style> </style>
在咱們的主入口main.jsreact
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/...
這樣,能保證組件每次調用的都是render函數,使用render函數生成VNode。git
咱們把Vue的實例掛載到#app
, 會調用實例裏面的render方法,生成虛擬DOM。來看看什麼是虛擬節點,把例子修改一下。github
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節點。那麼就能夠直接找到所對應的節點,而後直接替換。那麼這個過程只會在本組件內發生,不會影響其餘的組件。因而組件與組件是隔離的。
例子以下:web
// 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('h1', ['hello world']) console.log('app:', app) return app } } </script>
咱們能夠看到,當main.js
中從新觸發render函數的時候,render方法裏面有引用App.vue這個子組件。可是並無觸發App.vue組件的的render函數。app
在一個組件內,什麼狀況會觸發render?
。dom
數據劫持是Vue的一大特點,原理官方已經講的不少了深刻響應式原理。在咱們給組件的data的屬性進行的賦值的時候(set),此屬性若是在組件內部初次渲染過程被引用(data的屬性被訪問,也就是數據劫持的get
), 包括生命週期方法或者render方法。因而會觸發組件的update(beforeUpdate -> render -> updated)。異步
注: 爲了防止data被屢次set從而觸發屢次update, Vue把update存放到異步隊列中。這樣就能保證屢次data的set只會觸發一次update。
當props會觸發組件的從新渲染是怎麼發生的呢?
ide
把父組件的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('h1', ['hello world']) console.log('app:', app) return app } } </script>
截圖以下:
在main.js
中 state 狀態發生了變化,由false
=> true
, 觸發了自身與子組件的render方法。
上面的內容是本人的一些使用心得,因爲水平有限, 內容有些錯誤或者表達不當。多歡迎大神來指導