vue中插槽詳解---從slot,slot-scope到v-slot的變化

前言

vue 插槽,目前到3.0有3種方式,第一種,在2.6之前使用的是slot 和 slot-scpe 2.6後已被官方廢棄,但在2.x版本仍被支持,第二種是vue 在2.6版本後更新的新指令 v-slot 來替代slot 和slot-scpe

那麼什麼是插槽呢,作用又是什麼

插槽,簡單說,插槽就是杯子,杯子裏面裝的是飲料還是牛奶,由外部倒入什麼來決定 ,就好比下面的代碼,我需要一個子組件,他有部分內容,需要根據我當前頁面需要來展示,我如何將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>
            <div solt="header">頭部標題</div>
             <div >顯示的內容</div>
             <div  slot="footer">尾部</div>
        </layout>
    </div>
</template>


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

**tip:**當你的子組件中 如layout 中並不存在,slot這個元素,那麼在父頁面中 這個標籤中的內容都會被拋棄

作用域插槽

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

作用域插槽,就是能讓插槽內容訪問到子組件中才有的數據

//父級
<template>
    <div>
        <cup>
            <div solt="size" slot-scope="data">
                {{data.msg}}
    		</div>
        </cup>
    </div>
</template>
//cup子組件
<template>
    <div>
        <slot name="size" :msg="msg"></slot>
    </div>
</template>
<script>
export default {
    data(){
    		return{
    			msg:'300mL大小的杯子'
			}
		}
}
</script>

解構prop的寫法

下面寫法等同上面

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

上述是vue2.6之前的版本,之後vue官方廢棄了上面的語法,改爲v-solt來代替,然後大家就想知道,區別在哪呢

首先就是 用一個指令合併了solt 和solt-scope2個attribute,寫法更加簡潔,其次就是語義化更明顯

2.6之前的寫法會出現作用域混淆的問題

例:

<one>
  <two slot-scope="one"> //接受到的作用域,是外層one組件的,而不是當前組件two
    <three slot-scope="two">
      <template slot-scope="three">
        {{ one }} {{ two }} {{ three }}
      </template>
    </three>
  </two>
</one>

如上述代碼一層子組件時,你能清晰的看清作用域是哪一個組件的,但多層嵌套後,每一層接收的作用域是外層組件的而不是當前組件的,這樣,就會不清晰,所以vue希望能實現,當前組件,接受當前組件的作用域

於是就有了v-solt 下面是改良後的代碼,是否更加的清晰了

<one v-slot="one">
  <twotwo v-slot="two">  //接收到的作用域爲當前two組件的
    <three v-slot="three">
      {{ one }} {{ two }} {{ three }}
    </three>
  </bar>
</one>

如果沒看懂 那麼下面來闡述,v-solt的使用變化,

v-solt 默認插槽

和原來不同便是,原來的solt屬性可以定義在任何元素上,現在v-solt只能是template元素上,只有一種額外情況,就是獨佔默認插槽,我們先看常規情況。v-slot:default這種就是具名的寫法

父組件
<template>
    <item > 
        <template v-slot:default> // v-slot:default可以不加,只能定義在template上
            <div>裝一杯牛奶</div>
		</template>
        	
     <item>
</template>
      
     
 //item子組件
     <template>
          <div>
              <slot ></slot>//默認插槽   
              <h1>
               我是杯子  
         	</h1>
              
         </div>
     </template>
     

未具名的solt 元素,自動默認名爲default 你可以不寫,當然如果你要看的更清晰,

獨佔默認插槽

提供內容只有默認插槽,上述就滿足此條件,所以我們可以這樣寫

父組件
<template>
    <item v-slot:default> //v-slot:default可以不加
            <div>裝一杯牛奶</div>
     <item>
</template>
      
     
 //item子組件
     <template>
          <div>
              <slot ></slot>//默認插槽   
              <h1>
               我是杯子  
         	</h1>
              
         </div>
     </template>

v-solt具名插槽

//父級
<template>
    <div>
        <layout>
      	 <template v-slot:header>//v-slot指令使用插槽
            <div >頭部標題</div>
         </template>

           <div >顯示的默認內容</div>
                    <!--
         			或者
             		<template v-slot:default>
                        <div >顯示的默認內容</div>
                     </template>	
             		-->
		<template v-slot:footer>
            <div >尾部</div>
         </template>
         
        </layout>
    </div>
</template>


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

v-solt作用域插槽

這是改動最大地方

//父級
<template>
    <div>
        <cup>
            <template v-slot:default="data"> //具名寫法
                    <div>
                      {{data.msg}}   
                 </div>
			</template>
			   <!--
         			或者
             		<template v-slot="data">
                        <div > {{data.msg}}   </div>
                     </template>	
             		-->
		
        </cup>
    </div>
</template>
//cup子組件
<template>
    <div>
        <slot  name="size" :msg="msg"></slot >
    </div>
</template>
<script>
export default {
    data(){
    		return{
    			msg:'300mL大小的杯子'
			}
		}
}
</script>

當爲獨佔默認插槽時,v-solt可以省略default不寫

注意默認插槽的縮寫語法不能和具名插槽混用,因爲它會導致作用域不明確下面是官方的例子

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

所以當出現多個插槽的時候,請使用完整的基於template 的語法

解構props的寫法

這裏使用上面cup組件的例子

<template>
    <div>
        <cup>
            <template v-slot:default="{msg}"> //解構
                    <div>
                      {{msg}}   
                 </div>
			</template>
			 
        </cup>
    </div>
</template>

v-slot 的解構還提供 重命名的寫法

<template>
    <div>
        <cup>
            <template v-slot:default="{msg : size}"> //別名
                    <div>
                      {{size}}   
                 </div>
			</template>
			 
        </cup>
    </div>
</template>

動態插槽名

v-slot 支持2.6的動態參數寫法

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

這裏的 attributeName 會被作爲一個 JavaScript 表達式進行動態求值,求得的值將會作爲最終的參數來使用。例如,如果你的 Vue 實例有一個 data property attributeName,其值爲 "header",那麼這個綁定將等價於 v-slot:header

插槽的縮寫

2.6後插槽 可以把參數之前的所有內容 (v-slot:) 替換爲字符 #。例如 v-slot:header 可以被重寫爲 #header

v-slot:後面必須有值,不可寫成#="{data}"

<template>
    <div>
        <cup>
            <template #default="msg"> 
                    <div>
                      {{size}}   
                 </div>
			</template>
			 
        </cup>
    </div>
</template>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章