vue2.0 slot用法


學習vue.js也有一段時間了,關於slot這一塊,也看了不少次了,總感覺有點迷迷糊糊,不知其然也不知其所以然,抽出一段完整的時間,再一次仔細學習。稍微有點理解了,在此稍作記錄,好記性不如爛筆頭嘛!

vue關於實現slot的原因也給與了解釋:

為了讓組件可以組合,我們需要一種方式來混合父組件的內容與子組件自己的模板。這個過程被稱為內容分發 (即 Angular 用戶熟知的“transclusion”)。
Vue.js 實現了一個內容分發 API,參照了當前 Web Components 規范草案,使用特殊的 <slot> 元素作為原始內容的插槽。

  也就是說slot的主要作用是“內容分發”,所以才實現<slot>元素的,那么究竟什么才是內容分發呢?

  從我個人淺顯的理解就是:

    當一個子組件當中,大部分元素是可共用的,只有部分略有差別的時候,這時候就可以通過父組件實現內容分發,從而定制子組件當中略有差別的內容。

  舉例來說:

  

以當前兩個頁面來說,學校排行和作品排行的列表基本上就是一樣,但是不可否認,他們也不完全一樣,所以此時如果使用內容分發的話,可能相對能夠更簡便的吧(當然,使用各自子組件也必然能夠實現相同效果)!

RankSchool.vue和RankWorks.vue兩個文件作為父組件,都需要調用RankTable.vue

先看一下RankTable.vue的內容:

<template>
  <table>
    <slot name="title"><caption>作品排行</caption></slot>
    <thead>
      <slot name="header"> 
        <tr>
          <th>序號</th>
          <th>姓名</th>
          <th>ID</th>
          <th>學校</th>
          <th>點贊數</th>
        </tr>
      </slot>
    </thead>
    <tbody>
      <slot>
        <tr v-for="(item, index) in items" :key="item.id + index">
          <td>{{index + 1}}</td>
          <td>{{item.name}}</td>
          <td>{{item.id}}</td>
          <td>{{item.school}}</td>
          <td>{{item.praise}}</td>
        </tr>
      </slot>
    </tbody>
  </table>
</template>

  至於里面的數據,暫不考慮,其實子組件文件還是比較簡單的,就是子組件的所有內容,唯一的區別之處在於,在有可能做內容分發的地方使用<slot>標簽,我們當前文件有三個地方可能產生內容分發,

  <caption>作品排行</caption>

  兩個排行榜名稱應該是不一樣的,所以使用<slot name="title"></slot>將<caption>作品排行</caption>這個標簽包裹起來。

  第二處內容分發的地方在table的表頭,也就是thead標簽。

        <tr>
          <th>序號</th>
          <th>姓名</th>
          <th>ID</th>
          <th>學校</th>
          <th>點贊數</th>
        </tr>
 
        

  我們使用<slot name="header"></slot>將這一段包裹。

  還有一處自然是真正的列表部分了,

        <tr v-for="(item, index) in items" :key="item.id + index">
          <td>{{index + 1}}</td>
          <td>{{item.name}}</td>
          <td>{{item.id}}</td>
          <td>{{item.school}}</td>
          <td>{{item.praise}}</td>
        </tr>    

  也使用<slot></slot>包裹,允許有匿名的slot,但是為了清晰而言,建議除非當前組件內只有一個slot,否則就將所有slot予以命名。

  由於我們的子組件基本上是以“作品排行”的內容作出來的頁面,所以在RankWorks.vue中調用時,就直接調用就好了

<template>
  <div class="ranking">
    <loading v-if="loading"></loading>
    <rank></rank>
  </div> 
</template>
<script>
  import Rank from "./RankTable"
export default {
  components: {
      Rank
    }
}
</script>

  簡單方便,與正常的組件調用沒有任何區別。

  而在“學校排行”組件RankSchool.vue文件中調用的時候,就需要我們注意了,得做好內容分發,不然展現的列表就與“作品排行”一樣了。

<template>
  <div class="ranking">
    <loading v-if="loading"></loading>
    <rank>
      <caption slot="title">學校排行</caption>
      <tr slot="header">
        <th>序號</th>
        <th>學校</th>
        <th>綜合得分</th>
      </tr>
      <tr v-for="(item, index) in lists" :key="item.id">
        <td>{{index + 1}}</td>
        <td>{{item.school}}</td>
        <td>{{item.score}}</td>
      </tr>
    </rank>
  </div>
</template>

  其實,也就是在<rank></rank>標簽內添加內容,以標簽上加slot="名稱"來區分當前內容將要分發到子組件哪一個slot當中,如果都沒有slot="名稱",會將所有內容填充的子組件的<slot></slot>當中,也就是子組件當中匿名的slot當中。

  可以總結出來這么一個簡單方法:

  子組件按照平時寫組件的習慣寫,等到子組件完全寫好之后,在父組件調用時,發現哪里需要分發內容的,回到子組件當中,使用<slot name="名稱"></slot>將子組件中需要替換的這一部分給包裹起來。是不是很簡單呢?

  可能在簡單項目,或者多數項目當中,未必需要使用<slot></slot>內容分發,但是掌握<slot></slot>不是也能精簡我們的vue文件么?


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM