使用vue
這麼久了,可是對render
函數仍是不怎麼熟悉,因此寫篇文章加深理解和記憶!方便往後熟練使用。javascript
mian.js中的new Vue中會傳入render: h => h(App)
html
那麼這個h
其實能夠用來建立元素。vue
他的第一個參數是必選參數java
第二個和第三個都是可選參數數組
第一個參數就是當前要渲染的組件或者標籤,也能夠是個函數app
第二個參數一個配置對象,裏面能夠傳遞一些html
自帶的原生屬性dom
第三個參數能夠是字符串或者數組 示例代碼:函數
new Vue({
render: h => {
return h('div',{
attrs:{
id:'box'
},
style:{
color:'red'
}
},'Dreams')
}
}).$mount('#app')
複製代碼
這裏咱們用render
函數生成了一個id
爲box
,顏色爲紅色
,文本爲Dreams
的div
元素。ui
問題又來了,假設咱們渲染一個組件,組件裏面要進行傳值,那麼該怎麼書寫?spa
new Vue({
render: h => {
return h(CountTo,{
props:{
endVal:100
}
})
}
}).$mount('#app')
複製代碼
那麼這裏咱們就能夠在render
函數裏使用props
對組件進行傳值操做了。
上面這個是一個數字過渡組件,咱們傳遞endVal是爲了告訴他到多少時中止
在此基礎上,咱們若是想給組件綁定事件呢?
new Vue({
render: h => {
return h(CountTo,{
props:{
endVal:100
},
on:{
'on-animation-end':(val) => {
console.log(val)
}
}
})
}
}).$mount('#app')
複製代碼
實際上這裏監聽了一個事件,on-animation-end
這個事件實際上是CountTo
組件經過$emit
派發出來的. 而後咱們又想給這個組件最外層綁定一個點擊事件該怎麼作?
new Vue({
render: h => {
return h(CountTo,{
props:{
endVal:100
},
on:{
'on-animation-end':(val) => {
console.log(val)
}
},
nativeOn:{
'click':() => {
console.log('click')
}
}
})
}
}).$mount('#app')
複製代碼
而後咱們又想給這個組件定義一個class
類名怎麼辦?
new Vue({
render: h => {
return h(CountTo,{
'class':['count-to',true ? 'aa' : 'bb'],
props:{
endVal:100
},
on:{
'on-animation-end':(val) => {
console.log(val)
}
},
nativeOn:{
'click':() => {
console.log('click')
}
}
})
}
}).$mount('#app')
複製代碼
那麼咱們還想使用指令和插槽而且獲取dom
怎麼辦?
new Vue({
render: h => {
return h(CountTo,{
'class':['count-to',true ? 'aa' : 'bb'],
props:{
endVal:100
},
domProps:{
//dom上的一些屬性,
//由於如今是組件因此這樣寫會報錯
innerHTML:'123'
},
on:{
'on-animation-end':(val) => {
console.log(val)
}
},
nativeOn:{
'click':() => {
console.log('click')
}
},
directives:[],
slot:'default',
key:'',
ref:'',
scopedSlots:{},
})
}
}).$mount('#app')
複製代碼
那假設如今須要給一個標籤添加元素怎麼添加?
咱們把上面的幹掉!
new Vue({
render: h => h('div','123')
}).$mount('#app')
複製代碼
這裏的123是第三個參數,第二個參數咱們不寫直接留空
因此頁面上會渲染出
<div>123</div>
複製代碼
若是咱們要在div
元素裏添加多個子元素呢? 那麼確定是個數組。
new Vue({
render: h => h('div',{},[
h('span','111'),
h('span','222'),
])
}).$mount('#app')
複製代碼
那麼如今div
裏就有兩個span
標籤了
<div>
<span>111</span>
<span>222</span>
</div>
複製代碼
那麼咱們生成的東西若是不少且不固定呢?
那麼這裏如何使用循環呢?
那麼這裏咱們新建一個組件文件
裏面的內容是這樣的
new Vue({
render: h => h('div',{},[
h('ul',{
on:{
'click':(event) => {
console.log(event)
}
}
},[
h('li',{
on:{
'click':event => {
console.log(event)
}
}
})
])
])
}).$mount('#app')
複製代碼
那麼如今div
裏就有一個ul
標籤包含一個li
標籤了
<div>
<ul>
<li></li>
</ul>
</div>
複製代碼
在render
裏咱們實際上是沒辦法使用v-for
指令的,因此咱們要本身實現這個方法
let list = [{name:'Dreams'},{name:'Dreams2'}]
const getLiEleArr = h => {
return list.map(item => h('li',{
on:{
'click':(event) => {
console.log(event)
}
}
},item.name))//標籤內的內容
}
複製代碼
這個方法寫好了以後咱們把剛剛上面的改造一下
new Vue({
render: h => h('div',{},[
h('ul',{
on:{
'click':(event) => {
console.log(event)
}
}
},getLiEleArr(h))
])
}).$mount('#app')
複製代碼
那麼這樣頁面上就成功的渲染出以下的標籤:
<div>
<ul>
<li>Dreams</li>
<li>Dreams2</li>
</ul>
</div>
複製代碼
同時li和ul也有點擊事件
這裏須要阻止事件冒泡,但render
函數裏也沒法使用vue
的.stop
修飾符 因此咱們須要給剛剛的click裏使用event.stopProgation()
來阻止
但又有問題來了,咱們知道使用v-for須要給每一個元素加上key
,但這裏咱們沒有該怎麼辦?
回到剛剛的代碼
let list = [{name:'Dreams'},{name:'Dreams2'}]
const getLiEleArr = h => {
return list.map((item,index) => h('li',{
on:{
'click':(event) => {
console.log(event)
}
},
key:`item_${index}`//這裏咱們加上key
},item.name))//標籤內的內容
}
複製代碼
那麼到這裏,相信你們也對render有了一個大概的瞭解了。
也就是說咱們平時在模板裏寫的東西其實最後都會被編譯爲相似上面的語法!
學好render函數在某些狀況下可讓咱們更好用js去控制一些細節的實現,但咱們也會發現,render略顯複雜,可是越複雜的東西才越有它存在的意義!
各位大佬,若是發現文中的錯誤,請指正,我會及時修改!
感謝大佬們能在百忙中能閱讀完這篇文章!