前端Vue:函式式元件

GeekQiaQia發表於2019-05-07

每天學習一個vue知識點呀

函式式元件特點:

  • 沒有管理任何狀態
  • 沒有監聽任何傳遞給它的狀態
  • 沒有生命週期方法
  • 它只是接收一些prop的函

我們將這樣的元件標記為functional:

  • 無狀態 == 無響應式資料
  • 無例項 == 無this上下文

函式式元件的優點:

  • 渲染開銷低,因為函式式元件只是函式;

函式式元件基本寫法:

 {
  functional: true,
  // Props 是可選的
  props: {
    // ...
  },
  // 為了彌補缺少的例項
  // 提供第二個引數作為上下文
  render: function (createElement, context) {
    // ...
  }
}
複製程式碼

元件需要的一切都是通過 context 引數傳遞,它是一個包含如下欄位的物件:

  • props: 提供所有prop的物件
  • children:VNode 子節點的陣列
  • slots: 一個函式,返回了包含所有插槽的物件
  • scoptedSlots:(2.6.0) 一個暴露傳入的作用域插槽的物件,也以函式形式暴露普通插槽
  • data:傳遞個元件的整個資料物件,作為createElement的第二個引數傳入元件
  • parent:對父元件的引用
  • listeners:(2.3.0+) 一個包含了:所有父元件為當前元件祖冊的事件監聽器物件,是data.on的一個別名
  • injections:(2.3.0+) 如果使用了inject選項,則改物件包含了:應當被注入的屬性;

使用場景1:包裝元件

  • 程式化地在多個元件中選擇一個來代為渲染;

  • 在將 children、props、data 傳遞給子元件之前操作它們; 下面是一個 smart-list 元件的例子,它能根據傳入 prop 的值來代為渲染更具體的元件:

      var EmptyList = { /* ... */ }
      
      var TableList = { /* ... */ }
      
      var OrderedList = { /* ... */ }
      
      var UnorderedList = { /* ... */ }
    
      Vue.component('smart-list', {
        functional: true,
        props: {
          items: {
            type: Array,
            required: true
          },
          isOrdered: Boolean
        },
        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
          )
        }
      })
    複製程式碼

slots() 和children的對比

前端Vue:函式式元件

分析:

從字面意思顯而易見:

  1. children,可以獲取當前元件節點的所有的子節點;

  2. slots()函式返回了所有的插槽物件; 舉例:

     <my-functional-component>
       <p v-slot:foo>
         first
       </p>
       <p>second</p>
     </my-functional-component>
    複製程式碼

對於以上示例元件:

  • children 會給你兩個段落標籤;
  • slots().default 只會傳遞第二個匿名段落標籤
  • slots().foo 會傳遞第一個具名段落標籤

總結:

  • 你可以選擇使用slots()讓元件感知某個插槽機制,也可以簡單地通過傳遞 children,移交給其它元件去處理

參考官網

相關文章