1|0函式元件和普通元件區別
- 渲染快
- 沒有例項,意味著沒有(this)
- 沒有生命週期(沒有響應式資料)
2|0元件函式的使用
2|1以區域性元件為例,將元件標記為 functional=ture;
因為函式式沒有例項,因此元件需要的一切都是通過 context
引數傳遞,它是一個包括如下欄位的物件:
props
:提供所有 prop 的物件children
: VNode 子節點的陣列slots
: 一個函式,返回了包含所有插槽的物件scopedSlots
: (2.6.0+) 一個暴露傳入的作用域插槽的物件。也以函式形式暴露普通插槽。data
:傳遞給元件的整個資料物件,作為createElement
的第二個引數傳入元件parent
:對父元件的引用listeners
: (2.3.0+) 一個包含了所有父元件為當前元件註冊的事件監聽器的物件。這是data.on
的一個別名。injections
: (2.3.0+) 如果使用了inject選項,則該物件包含了應當被注入的屬性。
在新增 functional: true
之後,需要更新我們的錨點標題元件的渲染函式,為其增加 context
引數,並將 this.$slots.default
更新為 context.children
,然後將 this.level
更新為 context.props.level
。
因為函式式元件只是函式,所以渲染開銷也低很多。
在作為包裝元件時它們也同樣非常有用。比如,當你需要做這些時:
- 程式化地在多個元件中選擇一個來代為渲染;
- 在將
children
、props
、data
傳遞給子元件之前操作它們。1 data() { 2 return { 3 changer:1 4 } 5 },
1 components: { 2 MyCmp:{ 3 functional:true, //必要的設定 4 render: function (createElement, context) { 5 function getcomp(cmp){ 6 console.info(this); //輸出為undefined,證明沒有例項 7 if(cmp==1){ 8 return comp1; 9 }else{ 10 return comp2 11 } 12 } 13 return createElement(getcomp(context.props.changer), 14 { 15 props:{ 16 cmpData:context.props.data //為子元件傳遞資料 17 } 18 } 19 ); 20 },
2|0定義要渲染的元件
3|0在父元件中使用
4|0 理解渲染函式的引數
接下來說一下
createElement
接受的引數:第一個引數:可以是 {String | Object | Function}
不管是那種型別,最終返回到都是需要渲染的普通DOM標籤,
第二個引數:是一個物件,這個引數是可選的,定義了需要渲染元件的引數,相對於普通HTML標籤的屬性是一樣的。
還可以自定義指令的,Vue特有的東西,只是抽象一些,沒有直接用Vue.directive()用起來直觀。
第三個引數:子級虛擬節點,如果你這個節點只是單節點,沒有巢狀節點,這個引數可以忽略。如果有的你就要使用一個資料陣列的值位cerateElement()返回的虛擬節點。套路都是一樣的。
1 // @returns {VNode} 2 createElement( 3 // {String | Object | Function} 4 // 一個 HTML 標籤名、元件選項物件,或者 5 // resolve 了上述任何一種的一個 async 函式。必填項。 6 'div', 7 8 // {Object} 9 // 一個與模板中屬性對應的資料物件。可選。 10 { 11 // 與 `v-bind:class` 的 API 相同, 12 // 接受一個字串、物件或字串和物件組成的陣列 13 'class': { 14 foo: true, 15 bar: false 16 }, 17 // 與 `v-bind:style` 的 API 相同, 18 // 接受一個字串、物件,或物件組成的陣列 19 style: { 20 color: 'red', 21 fontSize: '14px' 22 }, 23 // 普通的 HTML 特性 24 attrs: { 25 id: 'foo' 26 }, 27 // 元件 prop 28 props: { 29 myProp: 'bar' 30 }, 31 // DOM 屬性 32 domProps: { 33 innerHTML: 'baz' 34 }, 35 // 事件監聽器在 `on` 屬性內, 36 // 但不再支援如 `v-on:keyup.enter` 這樣的修飾器。 37 // 需要在處理函式中手動檢查 keyCode。 38 on: { 39 click: this.clickHandler 40 }, 41 // 僅用於元件,用於監聽原生事件,而不是元件內部使用 42 // `vm.$emit` 觸發的事件。 43 nativeOn: { 44 click: this.nativeClickHandler 45 }, 46 // 自定義指令。注意,你無法對 `binding` 中的 `oldValue` 47 // 賦值,因為 Vue 已經自動為你進行了同步。 48 directives: [ 49 { 50 name: 'my-custom-directive', 51 value: '2', 52 expression: '1 + 1', 53 arg: 'foo', 54 modifiers: { 55 bar: true 56 } 57 } 58 ], 59 // 作用域插槽的格式為 60 // { name: props => VNode | Array<VNode> } 61 scopedSlots: { 62 default: props => createElement('span', props.text) 63 }, 64 // 如果元件是其它元件的子元件,需為插槽指定名稱 65 slot: 'name-of-slot', 66 // 其它特殊頂層屬性 67 key: 'myKey', 68 ref: 'myRef', 69 // 如果你在渲染函式中給多個元素都應用了相同的 ref 名, 70 // 那麼 `$refs.myRef` 會變成一個陣列。 71 refInFor: true 72 }, 73 74 // {String | Array} 75 // 子級虛擬節點 (VNodes),由 `createElement()` 構建而成, 76 // 也可以使用字串來生成“文字虛擬節點”。可選。 77 [ 78 '先寫一些文字', 79 createElement('h1', '一則頭條'), 80 createElement(MyComponent, { 81 props: { 82 someProp: 'foobar' 83 } 84 }) 85 ] 86 )