[Vue] slot詳解,slot、slot-scope和v-slot

v-slot

slot是什麼

slot,也稱插槽,能夠類比爲插卡式的FC遊戲機,遊戲機(子組件)暴露卡槽(插槽)讓用戶插入不一樣的遊戲磁條(自定義內容),遊戲機會讀取並加載磁條裏的遊戲。
Vue的slot,是組件的一塊HTML模版,這塊模版由使用組件者即父組件提供。能夠說是子組件暴露的一個讓父組件傳入自定義內容的接口。 javascript

FC-slot

slot的做用

讓用戶能夠拓展組件,去更好地複用組件和對其作定製化處理。
舉一些例子,好比佈局組件、表格列、下拉選項css

slot怎麼用

slot的用法能夠分爲三類,分別是默認插槽、具名插槽和做用域插槽
子組件中:html

  • 插槽用<slot>標籤來肯定渲染的位置,裏面放若是父組件沒傳內容時的後備內容
  • 具名插槽name屬性來表示插槽的名字,不傳爲默認插槽
  • 做用域插槽在做用域上綁定屬性來將子組件的信息傳給父組件使用,這些屬性會被掛在父組件slot-scope接受的對象上。
// Child.vue
<template>
  <div>
    <main>
    <!-- 默認插槽 -->
        <slot>
          <!-- slot內爲後備內容 -->
          <h3>沒傳內容</h3>
        </slot>
    </main>

    <!-- 具名插槽 -->
    <header>
        <slot name="header">
          <h3>沒傳header插槽</h3>
        </slot>
    </header>

    <!-- 做用域插槽 -->
    <footer>
        <slot name="footer" testProps="子組件的值">
          <h3>沒傳footer插槽</h3>
        </slot>
    <footer>
  </div>
</template>

<style scoped> div{ border: 1px solid #000; } </style>
複製代碼

父組件中在使用時:vue

  • 默認插槽的話直接在子組件的標籤內寫入內容便可
  • 具名插槽是在默認插槽的基礎上加上slot屬性,值爲子組件插槽name屬性值
  • 做用域插槽則是經過slot-scope獲取子組件的信息,在內容中使用。這裏能夠用解構語法去直接獲取想要的屬性
// Parent.vue
<child>
  <!-- 默認插槽 --> <div>默認插槽</div> <!-- 具名插槽 --> <div slot="header">具名插槽header</div> <!-- 做用域插槽 --> <div slot="footer" slot-scope="slotProps"> {{slotProps.testProps}} </div> </child>
複製代碼

渲染結果爲 java

slot-demo

v-slot

在vue2.6中,上述的API被軟廢棄(3.0正式廢棄),取而代之的是內置指令v-slot,能夠縮寫爲【#】git

子組件用法保持不變,父組件中github

  • slot屬性棄用,具名插槽經過指令參數v-slot:插槽名 的形式傳入,能夠簡化爲 #插槽名
  • slot-scope屬性棄用,做用域插槽經過v-slot:xxx="slotProps"的slotProps來獲取子組件傳出的屬性
  • v-slot屬性只能在<template>上使用,但在【只有默認插槽時】能夠在組件標籤上使用
//Parent
<template>
  <child>
   <!--默認插槽-->
   <template v-slot>
     <div>默認插槽</div>
   </template>
   <!--具名插槽-->
   <template #header>
     <div>具名插槽</div>
   </template>
   <!--做用域插槽-->
   <template #footer="slotProps">
     <div>
      {{slotProps.testProps}}
     </div>
   </template>
  <child>
</template>
複製代碼

拓展用法:

  1. 一樣能夠經過解構獲取v-slot={user},
    還能夠重命名v-slot="{user: newName}"和定義默認值v-slot="{user = '默認值'}"
  2. 插槽名能夠是動態變化的 v-slot:[slotName]

注意:

  1. 默認插槽名爲default,能夠省略default直接寫v-slot
    縮寫爲#時不能不寫參數,寫成#default(這點全部指令都同樣,v-bind、v-on)
  2. 多個插槽混用時,v-slot不能省略default

做用域插槽的原理

slot本質上是返回VNode的函數,通常狀況下,Vue中的組件要渲染到頁面上須要通過
template >> render function >> VNode >> DOM 過程。 組件掛載的本質就是執行渲染函數獲得VNode,至於data/props/computed這些屬性都是給VNode提供數據來源。ide

在2.5以前,若是是普通插槽就直接是VNode的形式了,而若是是做用域插槽,因爲子組件須要在父組件訪問子組件的數據,因此父組件下是一個未執行的函數 (slotScope) => return h('div', slotScope.msg) ,接受子組件的slotProps參數,在子組件渲染實例時會調用該函數傳入數據。函數

在2.6以後,二者合併,普通插槽也變成一個函數,只是不接受參數了。佈局

大綱速記:

outline

僅做學習記錄。若有錯漏之處,敬請指正

參考

vue文檔-插槽
如何理解Vue.js的組件中的slot?
v-slot由來 - RFC

相關文章
相關標籤/搜索