一、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(雙花括號)語法就不能再次使用