1. 程式人生 > >vue render函數 函數組件化

vue render函數 函數組件化

func 3.0 ring 一切都 ria 同時 ner class tee

之前創建的錨點標題組件是比較簡單,沒有管理或者監聽任何傳遞給他的狀態,也沒有生命周期方法,它只是一個接受參數的函數

在這個例子中,我們標記組件為functional,這意味它是無狀態(沒有data),無實例(沒有this上下文)

一個函數化組件就像這樣:

Vue.component(‘my-component‘, { functional: true, // 為了彌補缺少的實例 // 提供第二個參數作為上下文 render: function (createElement, context) { // ... }, // Props 可選 props: { // ... } })

註意:在2.3.0之前的版本中,如果一個函數式組件想要接受props,則props選項是必須的,在2.3.0及以上的版本中,你可以省略props選項,所有組件上的屬性都會被自動解析為props。

組件需要的一切都是通過上下文傳遞的,包括:

  • props:提供props對象
  • children:VNode子節點的數組
  • slots:slots對象
  • data:傳遞給組件的data對象
  • parent:對父組件的引用
  • listeners:(2.3.0+)一個包含了組件上所註冊的v-on偵聽器的對象。這只是一個指向data.on的別名
  • injections:(2.3.0+)如果使用了inject選項,則該對象包含了應當被註入的屬性

在添加functional:true之後,錨點標題組件的render函數之間簡單更新增加context參數,this.$slots.default更新為context.children,之後this.level更新為context.props.level.

因為函數化組件只是一個函數,所以渲染開銷也低很多。然而,對持久化實例的缺乏也意味著函數化組件不會出現在vue devtools的組件樹裏。

在作為包裝組件時它們也非常有用,比如你需要做這些時:

  • 程序化的在多個組件中選擇一個
  • 在將children,props,data傳遞給子組件之前操作它們。

下面是一個依賴傳入props的值的smart-list組件例子,它能代表更多具體的組件:

var EmptyList = { /* ... */ } var TableList = { /* ... */ } var OrderedList = { /* ... */ } var UnorderedList = { /* ... */ }
Vue.component(‘smart-list‘, { functional: true, render: function (createElement, context) { function appropriateListComponent () { var items = context.props.items if (items.length === 0) return EmptyList if (typeof items[0] === ‘object‘) return TableList if (context.props.isOrdered) return OrderedList return UnorderedList } return createElement( appropriateListComponent(), context.data, context.children ) }, props: { items: { type: Array, required: true }, isOrdered: Boolean } })

slots()和children對比

你可能想知道為什麽同時需要slots()和children。slots().default不是和children類似的嗎?在一些場景中,是這樣,但是如果是函數式組件和下面的這樣的children呢?

<my-functional-component> <p slot="foo"> first </p> <p>second</p> </my-functional-component> 對於這個組件,children會給你兩個段落標簽,而slots().default只會傳遞第二個匿名段落標簽,slots().foo會傳遞第一個具名段落標簽。同時擁有children和slots(),因此你可以選擇讓組件通過slot()系統分發或者簡單的通過children接收,讓其他組件去處理。 模板編譯 你可能有興趣知道,vue的模板實際上是編譯成了render函數。這是一個實現細節,通常不需要關心,但如果你想看看模板的功能是如何編譯出來的,你會發現非常有趣,下面是一個使用vue.compile來實時編譯模板字符串的簡單demo:

<div>
<header>
<h1>I‘m a template!</h1>
</header>
<p v-if="message">
{{ message }}
</p>
<p v-else>
No message.
</p>
</div>

render:

function anonymous() {
  with(this){return _c(‘div‘,[_m(0),(message)?_c(‘p‘,[_v(_s(message))]):_c(‘p‘,[_v("No message.")])])}
}


staticRenderFns:
_m(0): function anonymous() {
  with(this){return _c(‘header‘,[_c(‘h1‘,[_v("I‘m a template!")])])}
}

vue render函數 函數組件化