vue.js 實踐總結(二)Render 函數

上一篇說了項目搭建和結構,這篇說說vue 的render 函數,比較核心的概念。去年寫過一點react,因此知道render 函數是用來建立虛擬dom 的,那個時候寫 jsx 仍是不亦樂乎的。列出幾個問題做爲這篇的結構:html

  • render 函數的做用?
  • 組件中的render 函數何時執行?
  • 何時須要在組件中寫 jsx ?

常遇到這個問題:前端

[Vue warn]: Failed to mount component: template or render function not definedvue

這個問題是因爲當前寫的組件沒註冊爲vue 組件,或者組件定義中沒有template/render,因此組件無法和具體的element 掛載到一塊兒,沒法完成渲染。react

render 的做用

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>
    );
}
複製代碼

從生命週期出發,render執行時機

與render 相關的生命週期

仍是得把組件的生命週期搬出來,created 鉤子函數是組件injection和reactivity 屬性初始化後,好比props、data 初始化,後面關鍵的:若是有template,則把視圖編譯爲render function,若是沒有則直接調用被override 的render 方法建立虛擬dom節點,而且把組件對應的 htmlElement 替換爲 組件的dom 結構和數據,最後觸發mounted 鉤子。bash

因此執行順序是 beforeMount -- render(h, data) -- mounted .babel

何時須要定義render

上面那個實例,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的概念。

參考文章:

官方文檔:渲染函數 & JSX

說說 VNode 節點

支持 jsx 語法的插件,transform-vue-jsx

被誤解的MVC和被神化的MVVM,rethinking-mvc-mvvm

相關文章
相關標籤/搜索