【Vue】徹底理解Vue中render函數與template的區別


一、render函數與template對比

VUE一般使用template來創建HTML,然后在有的時候,我們需要使用javascript來創建html,這時候我們需要使用render函數。

 

以下我們來做一個需求跟根據level等級來編寫對應等級的標題

template解析

<body>
   <div id="app">
       <h-title level=1>
           <p>li</p>
       </h-title>
       <h-title level=2>
           <p>li</p>
       </h-title>
   </div>
</body>

</html>
<scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
//在這里玩們需要通過v-if來進行判斷
   Vue.component("h-title", {
       template: `<div>
           <h1 v-if="level==1"><slot></slot></h1>
           <h2 v-else-if="level==2"><slot></slot></h2>
       </div>`,
       props: {
           level: {
               type: Number,
               required: true
          }
      }
  })

   let vm=newVue({
       el: "#app"
  })
</script>

render解析

<body>
   <divid="app">
       <h-titlelevel=1>
           <p>Alley</p>
       </h-title>
       <h-titlelevel=2>
           <p>Alley</p>
       </h-title>
   </div>
</body>

</html>
<scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
   Vue.component("h-title", {
       render:function(createElement){
           returncreateElement(
               "h"+this.level,
               this.$slots.default
          )
      },
       props: {
           level: {
               type: Number,
               required: true
          }
      }
  })

   letvm=newVue({
       el: "#app"
  })
</script>

 

二者對比我們不難看出render函數創建組件的方式更加的靈活,同時也能讓我們最大的發揮出JavaScript的編程能力

 

二、render函數詳解

Vue中的Render函數中有一個參數,這個參數是一個函數通常我們叫做h。其實這個h叫做createElement。Render函數將createElement的返回值放到了HTML中

createElement這個函數中有3個參數

  • 第一個參數(必要參數):主要用於提供DOM的html內容,類型可以是字符串、對象或函數

  • 第二個參數(類型是對象,可選):用於設置這個DOM的一些樣式、屬性、傳的組件的參數、綁定事件之類

  • 第三個參數(類型是數組,數組元素類型是VNode,可選):主要是指該結點下還有其他結點,用於設置分發的內容,包括新增的其他組件。注意,組件樹中的所有VNode必須是唯一的

 
        
// @return {VNode}
createElement(
 // {String | Object | Function}
 // 一個HTML標簽字符串,組件選項對象,或者一個返回值類型為String/Object的函數。該參數是必須的
 'div',

 // {Object}
 // 一個包含模板相關屬性的數據對象,這樣我們可以在template中使用這些屬性,該參數是可選的。
{
     attrs: {
        name: headingId,
        href: '#'+headingId
    },
     style: {
        color: 'red',
        fontSize: '20px'
    },
     'class': {
        foo: true,
        bar: false
      },
      // DOM屬性
      domProps: {
         innerHTML: 'baz'
      },
      // 組件props
       props: {
          myProp: 'bar'
      },
       // 事件監聽基於 'on'
       // 所以不再支持如 'v-on:keyup.enter' 修飾語
       // 需要手動匹配 KeyCode  
       on: {
           click: function(event) {
                event.preventDefault();
                console.log(111);
          }
        }
  }

 // {String | Array}
 // 子節點(VNodes)由 createElement() 構建而成。可選參數
 // 或簡單的使用字符串來生成的 "文本節點"。
[
   'xxxx',
   createElement('h1', '一則頭條'),
   createElement(MyComponent, {
     props: {
       someProp: 'xxx'
    }
  }),
   this.$slots.default
]
)

三、什么時候用render函數?

假設我們要封裝一套按鈕組件,按鈕有四個樣式(success、error、warning、default)。首先,你可能會想到如下實現

<template>
<divclass="btn btn-success"v-if="type === 'success'">{{ text }}</div>
<divclass="btn btn-danger"v-else-if="type === 'danger'">{{ text }}</div>
<divclass="btn btn-warning"v-else-if="type === 'warning'">{{ text }}</div>
</template>

 

雖然我們這樣實現沒有問題,但是如果現在有十幾個樣式的情況下我們就需要寫N多個判斷,如果遇到了這種情況我們就可以選擇使用render函數。

其實簡單的來說就是template適合簡單的組件封裝,然后render函數適合復雜的組件封裝

<script>
Vue.component("A-button", {
       props: {
           type: {
               type: String,
               default: 'default'
          },
           text: {
               type: String,
               default: '按鈕'
          }
      },
       computed: {
           tag() {
               switch(this.type) {
                   case'success':
                       return1;
                   case'danger':
                       return2;
                   case'warning':
                       return3;
                   default:
                       return1;
              }
          }
      },
       render(h) {
           returnh('div', {
               class: {
                   btn: true,
                   'btn-success': this.type==='success',
                   'btn-danger': this.type==='danger',
                   'btn-warning': this.type==='warning'
              },
               domProps: {
                   //innerText: this.text,
              },
               on: {
                   click: this.handleClick
              }
          },
           this.$slots.default
          );
      },
       methods: {
           handleClick() {
               console.log('-----------------------');
               console.log('li');
          }
      }
  })

   letvm=newVue({
       el: "#app"
  })
</script>

四、template與render函數對比

相同之處:

render 函數template 一樣都是創建 html 模板

不同之處:

  • Template適合邏輯簡單,render適合復雜邏輯。

  • 使用者template理解起來相對容易,但靈活性不足;自定義render函數靈活性高,但對使用者要求較高。

  • render的性能較高,template性能較低。這一點我們可以看一下,下圖中vue組件渲染的流程圖可知。

  • 基於上一點,我們通過vue組件渲染流程圖知道,使用render函數渲染沒有編譯過程,相當於使用者直接將代碼給程序。所以,使用它對使用者要求高,且易出現錯誤

  • Render 函數的優先級要比template的級別要高,但是要注意的是Mustache(雙花括號)語法就不能再次使用


免責聲明!

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



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