開開森森學前端之render函數

前言

使用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函數生成了一個idbox,顏色爲紅色,文本爲Dreamsdiv元素。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略顯複雜,可是越複雜的東西才越有它存在的意義!

各位大佬,若是發現文中的錯誤,請指正,我會及時修改!

感謝大佬們能在百忙中能閱讀完這篇文章!

相關文章
相關標籤/搜索