1. 程式人生 > 實用技巧 >vue - 插槽詳解

vue - 插槽詳解

目錄

什麼是插槽

官方文件是這樣說明插槽的:

Vue 實現了一套內容分發的 API, 這套 API 的設計靈感源自 Web 規範草案, 將 <slot> 元素作為承載分發內容的出口。

插槽,簡單說,插槽就是杯子,杯子裡面裝的是飲料還是牛奶,由外部倒入什麼來決定 ,就好比下面的程式碼,有一個子元件,他有部分內容,需要根據我當前頁面需要來展示,將html模板傳入到子元件就需要使用插槽。

如下所示,定義一個子元件item,用solt標籤定義一個預設插槽,為在父元件使用時,需要傳遞到item元件的模板,佔個位置。 這樣在父元件在item子元件中編寫的html模板就會被渲染到子元件。

預設插槽

// 父元件
<template>
<tab>
    <item >
        <div>裝一杯牛奶</div>
    <item>
<tab>
</template>
  
// item子元件
<template>
    <div>
        <slot></slot>  //預設插槽   在父元件使用item子元件,item標籤包裹的內容將預設被渲染到子元件的solt中
        <h1>我是杯子</h1>           
    </div>
</template>

這樣的好處,顯而易見,可以讓元件模組化更清晰,同時複用性更高。不至於我要一杯茶,我就要定義一個元件,我要一杯牛奶我又定義一個元件,有了插槽,我只需要定義一個杯子,要喝什麼由使用的傳入內容決定。

上述程式碼也叫預設插槽,就是預設把模板全部渲染到 solt 中,如果需要指定渲染,就需要使用具名插槽,簡單說就是起一個名字,告訴他小紅該坐那兒,小明該坐那兒

具名插槽

//父級
<template>
    <div>
        <layout>
            <template v-solt:header>頭部標題</template>
            <div>顯示的內容</div>
            <template v-solt:footer>尾部</template>
        </layout>
    </div>
</template>

//layout子元件
<template>
    <div>
        <layout>
            <h1>layout子元件</h1>
            <slot name="header"></slot>  //這種就叫具名插槽
            <slot></slot>   //如果不指定名字,就會將模板中未匹配到的內容渲染到預設插槽中,這裡為顯示的內容
            <slot name="footer"></slot>
        </layout>
    </div>
</template>

一個不帶 name 的 <slot> 出口會帶有隱含的名字“default”。

在向具名插槽提供內容的時候, 我們應該在<template> 元素上使用 v-slot 指令, 並以 v-slot 的引數的形式提供其名稱: v-slot:heade

現在 <template> 元素中的所有內容都將會被傳入相應的插槽。 任何沒有被包裹在帶有 v-slot 的 <template> 中的內容都會被視為預設插槽的內容

作用域插槽

父元件提供了模板給子元件,那麼子元件如何反饋給父元件呢,例如:我定義了一個杯子,我需要告訴使用的人,我這個杯子,只能裝300mL,這時我們就需要用v-slot來接收子元件上通過v-bind繫結的值。

作用域插槽,就是能讓插槽內容訪問到子元件中才有的資料

//父級
<template>
    <div>
        <cup>
            <template v-slot:size="data">   // 這裡將包含所有插槽 prop 的物件命名為 data, 也可以命名為其他的名字 
                  {{ data.msg }}
            </template>
            // vue 2.6 之前的寫法, 用 slot 接收 name, slot-scope 接收子元件繫結的資料
            //<div solt="size" slot-scope="data">
            //    {{data.msg}}
    	    //</div>
        </cup>
    </div>
</template>

//cup子元件
<template>
    <div>
        <slot name="size" :msg="msg"></slot>  // 繫結在 <slot> 元素上的特性被稱為插槽 prop。
    </div>
</template>
<script>
export default {
    data(){
    	return{
    	    msg:'300mL大小的杯子'
	}
    }
}
</script>

解構prop的寫法,ES6 語法, 與上面的寫法等價

//父級
<template>
    <div>
        <cup>
            <template v-slot:size="{ msg }">    
                  {{ msg }}
            </template>

            // 解構 並重命名
            //<template v-slot:size="{ msg : info }">    
            //      {{ info }}
            //</template>
        </cup>
    </div>
</template>

上面有說到 vue2.6之前插槽的版本,之後vue官方廢棄了上面的語法,改為v-solt來代替,區別在於

  • vue 2.6 之後的版本 v-slot 指令合併了solt 和solt-scope 這兩個attribute,寫法更加簡潔
  • 語義化更明顯
  • 2.6之前的寫法會出現作用域混淆的問題

獨佔預設插槽

v-slot 只能新增在一個 <template> 上 (只有一種例外情況), 這一點和已經廢棄的 slot 特性不同。而這個例外就是 獨佔預設插槽。

當被提供的內容只有預設插槽時, 元件的標籤才可以被當作插槽的模板來使用。 這樣我們就可以把 v-slot 直接用在元件上:

父元件
<template>
    <item v-slot:default="data"> //v-slot:default可以不加 v-slot="data"
        {{ data.msg }}
    <item>
</template>
      
     
//item子元件
     <template>
         <div>
             <slot :msg="msg"></slot>//預設插槽         
         </div>
     </template>

預設插槽的縮寫語法不能和具名插槽混用,因為它會導致作用域不明確。下面是官方的例子:

<!-- 無效,會導致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

注意:只要出現多個插槽, 請始終為所有的插槽使用完整的基於 <template> 的語法

動態插槽名

v-slot 支援2.6的動態引數寫法

<layout>
  <template v-slot:[attributeName]>
    ...
  </template>
</layout>

這裡的 attributeName 會被作為一個 JavaScript 表示式進行動態求值,求得的值將會作為最終的引數來使用。例如,如果你的 Vue 例項有一個 data property attributeName,其值為 "header",那麼這個繫結將等價於 v-slot:header。

具名插槽的縮寫

v-slot 也有縮寫, 即把引數之前的所有內容( v-slot: ) 替換為字元 # 。 例如 v-slot:header 可以被重寫為 #header

//父級
<template>
    <div>
        <layout>
            <template #header>頭部標題</template>  // 具名插槽的縮寫
            <div>顯示的內容</div>
            <template v-solt:footer>尾部</template>
        </layout>
    </div>
</template>

//layout子元件
<template>
    <div>
        <layout>
            <h1>layout子元件</h1>
            <slot name="header"></slot>  //這種就叫具名插槽
            <slot></slot>   //如果不指定名字,就會將模板中未匹配到的內容渲染到預設插槽中,這裡為顯示的內容
            <slot name="footer"></slot>
        </layout>
    </div>
</template>

注意: 該縮寫只在其有引數(例如:name)的時候才可用。

參考:https://blog.csdn.net/marendu/article/details/106288627