render 函數(shù),大部分工老油條,應(yīng)該是比較了解了,但是可能有些初出茅廬的小年輕們,不是很了解,并且嚴(yán)老濕也去網(wǎng)上查閱了一些相關(guān)的文章,總結(jié)了一下,不夠系統(tǒng),所以今天簡(jiǎn)單聊一下,循環(huán)漸進(jìn)
render 函數(shù)是什么
? 平常我們寫(xiě) <template> 里面所使用模板HTML語(yǔ)法組建頁(yè)面的,其實(shí)在 vue 中都會(huì)編譯成 render 函數(shù),因?yàn)?code>vue 中采用的是 虛擬DOM 所以拿到template模板時(shí)也要轉(zhuǎn)譯成 VNode(virtual node 虛擬節(jié)點(diǎn)) 函數(shù)
插一嘴 虛擬DOM 與 真實(shí)DOM 的區(qū)別
? 虛擬DOM不會(huì)進(jìn)行排版與重繪操作 ,虛擬DOM就是把真實(shí)DOM轉(zhuǎn)換為Javascript代碼,并且真實(shí)DOM頻繁操作排版、重繪效率相比虛擬DOM 效率會(huì)低很多,比如原生操作真實(shí)DOM瀏覽器會(huì)從構(gòu)建DOM樹(shù)開(kāi)始從頭到尾執(zhí)行一遍流程。而虛擬DOM是用Object來(lái)代表一顆節(jié)點(diǎn),這個(gè)Object叫做VNode,然后使用兩個(gè)VNode進(jìn)行對(duì)比,根據(jù)對(duì)比后的結(jié)果修改真實(shí)DOM。
瀏覽器渲染引擎工作流程

虛擬DOM 與VNode又涉及到diff算法,所以我們先暫停這里,開(kāi)始我們的正文,當(dāng)然有興趣的小伙伴們可以去查閱相關(guān)資料
render 函數(shù)的使用
先看看我們平常vue中的寫(xiě)法
<template>
<div>
<h1>嚴(yán)老濕</h1>
</div>
</template>
如果使用render函數(shù)將是怎樣呢?
<script>
export default {
render(createElement){
// createElement:
// 第一個(gè)參數(shù)是標(biāo)簽名類型必須是String
// 第二個(gè)是屬性值 我們后面來(lái)講,類型是Object
// 第三個(gè)是子級(jí)虛擬節(jié)點(diǎn) (VNodes) 可以是String|Array
return createElement('h1',{},"嚴(yán)老濕")
}
}
</script>
這樣我們也是一樣的可以實(shí)現(xiàn) template 中的元素

動(dòng)態(tài)接收參數(shù)
修改以下上面的代碼,我們?cè)賮?lái)試試
<script>
export default {
props:{
tag:{
type:String,
required: true
}
},
render(createElement){
return createElement(this.tag,{},"嚴(yán)老濕")
}
}
</script>
在父組件中傳值給子組件動(dòng)態(tài)切換標(biāo)簽
<sub-components tag="button"></sub-components>

原來(lái)可以這樣操作,那我們?cè)谕纥c(diǎn)其他的唄
<script>
export default {
props: {
tag: {
type: String,
required: true,
},
data: {
type: Array,
required:true
},
},
render(createElement) {
return createElement(this.tag, {},
// 嵌套到 this.tag 元素上
this.data.map(item=>
createElement('li',{},item.toString())
)
);
},
};
</script>
父組件傳值
<sub-components tag="ul" :data="data"></sub-components>
data:["新冠病毒滅活疫苗首次亮相","遼寧副省長(zhǎng)盧柯拿下科學(xué)大獎(jiǎng)","闞清子說(shuō)朱一龍神秘"]
看看效果

createElement 的屬性
我們剛剛使用了createElement的第一個(gè)和第三個(gè)參數(shù)
現(xiàn)在來(lái)看看第二個(gè)參數(shù),為什么拿到后面來(lái)講了,因?yàn)槔锩娴臇|西比較多
嗯?重頭戲么
接著來(lái)看看就知道啦
class
<script>
export default {
props: {
tag: {
type: String,
required: true,
},
data: {
type: Array,
required:true
},
},
render(createElement) {
return createElement(this.tag, {},
this.data.map(item=>
createElement('li',{
// 首先上場(chǎng)的是class
class:'child-element'
// or
// domProps: {className: "child-element"},
},item.toString())
)
);
},
};
</script>

我們給li 標(biāo)簽加上了class之后,可以直接在元素上看到 child-element ,然后想修改樣式的呢,直接通過(guò)選擇器修改就好了,這就不用多說(shuō)了吧!
on
再來(lái)看看事件系列
<script>
export default {
props: {
tag: {
type: String,
required: true,
},
data: {
type: Array,
required:true
},
},
render(createElement) {
return createElement(this.tag, {},
this.data.map(item=>
createElement('li',{
domProps: {
className: "child-element"
},
// 在on中我們可以寫(xiě)需要的事件
on:{
// 點(diǎn)擊事件 點(diǎn)擊打印 Pointer Event
click:(e)=>{
console.log(e)
},
// mouseover
// mouseout
}
},item.toString())
)
);
},
};
</script>
打印結(jié)果:

里面還有很多好玩的東西可以去看看 vue2.0 官方文檔
https://cn.vuejs.org/v2/guide/render-function.html#createElement-%E5%8F%82%E6%95%B0
如 :style 、 attrs 、directives 等等....
vue組件
如果看過(guò) render 源碼的同學(xué)應(yīng)該知道,我們剛剛所說(shuō)的第一個(gè)參數(shù) tag 不僅僅可以是標(biāo)準(zhǔn)的html標(biāo)簽。tag 可以分為正常html標(biāo)簽 | vue組件 兩類 。之前已經(jīng)學(xué)了html標(biāo)簽,接下來(lái) 我們來(lái)看看vue組件
首先我們新建一個(gè) vue 組件
<template>
<div>
{{content}}
</div>
</template>
<script>
export default {
props:{
content:{
type:String
}
}
}
</script>
在render函數(shù)頁(yè)面中引入
<script>
// 引入組件
import Widget from './Widget'
export default {
render(createElement) {
// 傳入組件
return createElement(Widget, {
// 傳值 content
props:{
content:"hello CrazyYan"
}
});
},
};
</script>
ok 返回到頁(yè)面上,我們已經(jīng)看到了組件

我們學(xué)到這里,應(yīng)該知道
- render函數(shù)的作用
- 它的簡(jiǎn)單使用方法
- 幾個(gè)參數(shù)的作用
參考資料
https://cn.vuejs.org/v2/guide/