上一篇說了項目搭建和結構,這篇說說vue 的render 函數,比較核心的概念。去年寫過一點react,因此知道render 函數是用來建立虛擬dom 的,那個時候寫 jsx 仍是不亦樂乎的。列出幾個問題做爲這篇的結構:html
常遇到這個問題:前端
[Vue warn]: Failed to mount component: template or render function not definedvue
這個問題是因爲當前寫的組件沒註冊爲vue 組件,或者組件定義中沒有template/render,因此組件無法和具體的element 掛載到一塊兒,沒法完成渲染。react
render 函數其實是template 的底層方法,經過調用createElement(h)來建立dom節點,實際上做用就是負責組件視圖渲染的!createElement是render的核心方法。Vue編譯的時候會把template 編譯爲對應的render 方法,因此有了render方法就能夠不寫template 了!jquery
看實例:npm
<template>
<div class="right-panel">
<div class="right-panel-header">{title}</div>
<div class="right-panel-content">
{content}
</div>
</div>
</template>
複製代碼
若是不寫template,對應的render 則是api
render(h) {
return (
<div class="right-panel">
<div class="right-panel-header">{this.title}</div>
<div class="right-panel-content">
{this.content}
</div>
</div>
);
}
複製代碼
仍是得把組件的生命週期搬出來,created 鉤子函數是組件injection和reactivity 屬性初始化後,好比props、data 初始化,後面關鍵的:若是有template,則把視圖編譯爲render function,若是沒有則直接調用被override 的render 方法建立虛擬dom節點,而且把組件對應的 htmlElement 替換爲 組件的dom 結構和數據,最後觸發mounted 鉤子。bash
因此執行順序是 beforeMount -- render(h, data) -- mounted .babel
上面那個實例,panel content 內容能夠是外部傳入的一段內容(this.$props.content),假如內容很複雜呢,假如這個panel 組件須要接受用戶自定義的複雜content 呢? 這時候就須要接受外部傳入的函數來渲染一段dom。 這樣panel 只是個容器,把內容渲染交給外部模塊,其實是組件拆分和模塊化的思想,使得panel 組件能夠更好的複用。網絡
咱們把panel 的render 函數改成能夠接受外部函數:
render(h) {
let contentNode = (<div>default content</div>);
if (this.contentRender && this.contentRender instanceof Function) {
contentNode = this.contentRender(h, this.data);
// 把數據用外部函數來渲染成用戶想要的結構
}
console.warn(`rendering...`);
return (
<div class="right-panel">
<div class="right-panel-header">Panel Header</div>
<div class="right-panel-content">
{contentNode}
// 插入dom 結構
</div>
</div>
);
}
複製代碼
contenRender 的定義能夠是這樣的:
contentRender (h, data) {
return (<div>Current Data: {data['app']}</div>);
},
複製代碼
render 真的頗有趣,其實際上就是jquery 時代的 建立dom,構建dom tree 的過程 其實是生成VNode 虛擬DOM節點的過程,VNode 能夠被vue.js 映射爲真實的DOM tree。 掌握了render ,就能夠自由構建可複用的組件容器。建議詳細閱讀官方文檔,很是有用。
開發一個前端項目,不單單是視圖和組件邏輯,更重要的是數據服務,現代化前端幾乎都是數據驅動的。由於一個app 在組件初始化時完成了數據和視圖綁定,對視圖的監聽,隨着app 的運行,其實是不斷變化的數據在驅動視圖的變化。
基於MVC 的架構或 MVVM的架構,在不斷寫組件的過程當中,咱們不斷反思該如何寫一個組件,怎麼把多個組件集成到一個複雜組件中,組件中的邏輯部分是否應該合理拆分出其餘幾個通用的模塊/類。
好比api service 單獨處理api相關的,api service 裏面的網絡請求有能夠單獨出 network 層,爲了方便替換net 請求庫,還有許多通用的數據格式轉換層,都是能夠單獨成類或者service的概念。
參考文章: