Vue插槽:slot、slot-scope、v-slot

前言:v-slot 指令自 2.6.0 起被引入,提供更好的支持 slot 和 slot-scope 特性的 API 替代方案。在接下來全部的 2.x 版本中 slot 和 slot-scope 特性仍會被支持,但已經被官方廢棄且不會出如今 Vue 3 中。數據結構

slot(已廢棄)

①內容:假如父組件須要在子組件內放一些DOM,那麼這些DOM是顯示、不顯示、在哪一個地方顯示、如何顯示,就是slot分發負責的活app

②默認狀況下,該組件起始標籤和結束標籤之間的任何內容都會被拋棄函數

//父組件
<template>
    <div id="app">
        <son>我想顯示點內容</son>
    </div>
</template>

//子組件
<template>
    <div>
        <span>我是子組件</span>
    </div>
</template>

③單個slot:當父組件須要顯示一些東西在子組件裏時,只須要將這個<slot>放置於子組件想要顯示的地方便可,若沒有name,則爲默認插槽(匿名插槽),一個不帶name<slot>出口會帶有隱含的名字「default」。優化

//父組件
<template>
    <div id="app">
        <son>
       <div>我顯示出來了</div>
     </son> </div> </template> //子組件 <template> <div> <p><slot></slot></p> <p>我是子組件</p> </div> </template>

上述代碼中父組件等同於下面的代碼,二者之間的區別是是否將隱含的「default」寫出來this

//父組件
<template>
    <div id="app">
        <son>
            <div slot="default">我顯示出來了</div>
        </son>
    </div>
</template>

④多個slot:當須要多個插槽顯示在不一樣的地方時,須要給每一個插槽加上一個name,而且父組件內加上"slot=name",使二者之間具備有關聯性,這就是具名插槽spa

//父組件
<template>
    <div id="app">
        <son>
            <div slot="slotOne">我是插槽一</div>
            <div slot="slotTwo">我是插槽二</div>
            <div slot="slotThree">我是插槽三</div>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p><slot name="slotOne"></slot></p>
        <p><slot name="slotTwo"></slot></p>
        <p class="content">我是子組件</p>
        <p><slot name="slotThree"></slot></p>
    </div>
</template>

注:多個插槽也能有且最多隻能一個默認插槽code

⑤當沒有對應插槽的name時component

1)插槽裏沒有默認的內容,則會什麼的都不輸出對象

//父組件
<template>
    <div id="app">
        <son>
            <div>我想插入進去</div>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p class="content">我是子組件</p>
        <p><slot name="slotOne"></slot></p>
    </div>
</template>

 2)插槽內有默認內容,則會直接輸出插槽內的內容blog

//父組件
<template>
    <div id="app">
        <son>
            <div>我想插入進去</div>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p class="content">我是子組件</p>
        <p><slot name="slotOne">沒有對應name時,我會顯示</slot></p>
    </div>
</template>

⑥當具名插槽和默認插槽混合使用的時候,任何沒有包裹slot(或者slot="default")的都將視爲默認插槽的內容,對於包裹相同slot值的標籤會渲染在同一個位置

//父組件
<template>
    <div id="app">
        <son>
        <div>匿名插槽第一段內容</div>
        <div slot="slotOne">相同具名一</div>
        <div>匿名插槽第二段內容</div>
        <div slot="slotOne">相同具名二</div>
        匿名插槽第三段內容
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p style="border:1px solid #0ff"><slot></slot></p>
        <p style="border:1px solid #f00"><slot name="slotOne"></slot></p>
    </div>
</template>

slot-scope(已廢棄)

本文全部做用域插槽,子組件裏news的數據

<script>
export default {
    name: "name",
    data(){
        return{
            news:[
                '十九屆四中全會28日至31日在京召開',
                '珍愛和平團結合做 構建人類命運共同體',
                '法治是最好的營商環境',
                '夯實優化營商環境的法治基石',
                '中國營商環境全球排名再前進15名!'
            ],
        }
    }
}
</script>

①做用域插槽或者說是一個帶數據的插槽

//父組件
<template>
    <div id="app">
        <son>
            <template slot="news" slot-scope="newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li>
                </ul>
            </template>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p class="content">我是子組件</p>
        <p><slot name="news" :newsList = 'news'></slot></p>
    </div>
</template>

 

這裏有小坑:

1)這裏的 slot-scope 聲明瞭被接收的 prop 對象會做爲 newData 變量存在於 <template> 做用域中。你能夠像命名 JavaScript 函數參數同樣隨意命名 newData 。

2)這時的newData數據結構爲: 

newsData:{
    newsList:[
        '十九屆四中全會28日至31日在京召開',
        '珍愛和平團結合做 構建人類命運共同體',
        '法治是最好的營商環境',
        '夯實優化營商環境的法治基石',
        '中國營商環境全球排名再前進15名!'
    ]
}

3)slot-scope 特性也能夠直接用於非 <template> 元素 

<template>
    <div id="app">
        <son>
            <div slot="news" slot-scope="newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">{{item}}</li>
                </ul>
            </div>
        </son>
    </div>
</template>

②slot-scope接收到的值也可使用ES6解構

<template>
  <div id="app">
    <son>
      <div slot="news" slot-scope="{news}">
        <ul>
          <li v-for="(item,index) in news" :key="index">{{item}}</li>
        </ul>
      </div>
    </son>
  </div>
</template>

v-slot

重點來了,v-slot是 v2.6.0 引入的新的指令,目的是爲了更好的支持slot、slot-scope的特性(其實就是把兩個統一塊兒來),新人上位,老人就應該退居幕後,並輔佐一段時間,因此slot、slot-scope在v2.6.0正式廢棄(後續的2.x版本依舊支持,但不推薦),在未來的v3.x版本中正式廢除(就是3.x版本不支持不能用了)

①默認插槽寫法和之前沒什麼變化,v-slot主要針對具名插槽、做用域插槽

②具名插槽,v-slot:name

//父組件
<template>
    <div id="app">
        <son>
            <template v-slot:slotOne>我想顯示一點內容</template>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p><slot name="slotOne"></slot></p>
    </div>
</template>

這裏有小坑

1)除獨佔默認插槽的縮寫語法外,v-slot 只能添加在一個 <template> 上

③做用域插槽,v-slot:name = customName

綁定在 <slot> 元素上的特性被稱爲插槽 prop。如今在父級做用域中,咱們能夠給 v-slot 帶一個值來定義咱們提供的插槽 prop 的名字

//父組件
<template>
    <div id="app">
        <son>
            <template v-slot:news = "newsData">
                <ul>
                    <li v-for="(item,index) in newsData.newsList" :key="index">
                        {{index}}、{{item}}
                    </li>
                </ul>
            </template>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p><slot name="news" :newsList = 'news'></slot></p>
    </div>
</template>

在這個例子中,咱們選擇將包含全部插槽 prop 的對象命名爲 newsData,但你也可使用任意你喜歡的名字。

④做用域插槽支持ES6解構

將上述例子中父組件改一下

<template>
    <div id="app">
        <son>
            <template v-slot:news = "{newsList}">
                <ul>
                    <li v-for="(item,index) in newsList" :key="index">
                        {{index}}、{{item}}
                    </li>
                </ul>
            </template>
        </son>
    </div>
</template>

⑤獨佔默認插槽的縮寫語法

當子組件內只有默認插槽時,組件的標籤能夠被看成插槽的模板來使用。這樣咱們就能夠把 v-slot 直接用在組件上

//父組件
<template>
    <div id="app">
        <son v-slot="{news}">
            <ul>
                <li v-for="(item,index) in news" :key="index">
                    {{item}}
                </li>
            </ul>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p><slot :news="news"></slot></p>
    </div>
</template>

這裏有小坑

1)當子組件內只有默認插槽時,能夠省略default,寫做:v-slot = customName

2)當子組件內只有默認插槽時,若是v-slot也準備使用縮寫時(#),default不能被省略,寫做:#default = customName

⑥獨佔默認插槽的縮寫語法不能與具名插槽混合使用

//父組件
<template>
    <div id="app">
        <son v-slot="{news}">
            <ul>
                <li v-for="(item,index) in news" :key="index">
                    {{item}}
                </li>
            </ul>
            <div v-slot:mixinSlot>默認插槽的縮寫語法和具名插槽混用,致使做用域不明確</div>
        </son>
    </div>
</template>

//子組件
<template>
    <div>
        <p><slot :news="news"></slot></p>
        <p><slot name="mixinSlot"></slot></p>
    </div>
</template>

⑦動態插槽名,用來來定義動態的插槽名

在v2.6.0版本中新增動態參數,能夠用方括號([])括起來的 JavaScript 表達式做爲一個指令的參數,動態參數我將在另外一篇文章敘述

//父組件
<template>
    <div id="app">
        <son>
            <template v-slot:[slotName] ='{ news }'>
                <ul>
                    <li v-for="(item,index) in news" :key="index">{{item}}</li>
                </ul>
            </template>
        </son>
    </div>
</template>

<script>
import son from "./components/son";

export default {
    name: "App",
    components: {
        son
    },
    data(){
        return{
            isOK: false
        }
    },
    computed: {
        slotName(){
            return this.isOK ? 'slot1' : 'slot2'
        }
    },
};
</script>

//子組件
<template>
    <div>
        <slot name="slot1" :news='news'></slot>
        <slot name="slot2" :news='news2'></slot>
    </div>
</template>

<script>
export default {
    name: "name",
    data() {
        return {
            news: [
                "十九屆四中全會28日至31日在京召開",
                "珍愛和平團結合做 構建人類命運共同體",
                "法治是最好的營商環境",
                "夯實優化營商環境的法治基石",
                "中國營商環境全球排名再前進15名!"
            ],
            news2: [
                '27省份前三季度GDP出爐 16省份GDP增速跑贏全國',
                '新航季來了!這些航班將飛大興機場,坐飛機別走錯',
                '北方回暖南方雨連綿 江南等多地氣溫將創新低',
                '水潤民心 脫貧路上「領頭雁」  鐘聲',
                '看看第六屆世界互聯網大會國際組織說了啥'
            ]
        };
    }
};
</script>

印象中,好像沒什麼地方須要用到動態插槽名,若是有大大遇到須要使用,還請留言,很是感謝,上述栗子若是用v-if,語義更明朗

⑧v-slot縮寫爲:#

具名插槽縮寫爲:#name

做用域插槽縮寫

1)當爲匿名做用域插槽時:#default = customName(#=customName這種寫法爲報錯)

2)當爲具名做用域插槽時:#name = customName

相關文章
相關標籤/搜索