第二十四節(jié):Vue插槽:Vue具名插槽/作用域插槽/v-slot指令

1. 具名插槽

1.1 沒有使用具名插槽的問題

有的時候我們在使用子組件時,在子組件模板上不同的位置插入不同的內(nèi)容, 只有一個插槽顯然沒發(fā)滿足我們的需求,看示例:

需求如下:

  1. 子組件是一篇文章的結(jié)構(gòu)
  2. 父組件在調(diào)用子組件是給文章插入標題,正文,時間信息

示例代碼如下:

<div id="app">
     <!-- 使用組件 -->
     <my-child >
         <h2>這是一篇介紹vue插槽的文章</h2>
         <p>這是文章的第一段</p>
         <p>這是文章的第二段內(nèi)容</p>
         <p>這是文章的第三段內(nèi)容</p>

         <span>2020年5月1日</span>
     </my-child>

</div>

<!-- 組件模板 -->
<template id="mychild">
    <div class="article">
        <div class="title">
            <slot></slot>
        </div>
        <div class="contont">
            <slot></slot>
        </div>
        <div class="time">
            <slot></slot>
        </div>
    </div>
</template>

<script>
    //  組件選項對象
    let MyChild = {
        template: `#mychild`
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        components: {
            MyChild
        }
    })

</script>

結(jié)果:

image

示例結(jié)果說明:

  1. 通過示例結(jié)果發(fā)現(xiàn)和我們想的天差地別,此時每一個插槽都插入了所有的內(nèi)容, 顯然不符合預期
  2. 那么我們怎樣才能將分發(fā)的內(nèi)容指定到每一個具體的插槽上呢.

這個時候我們就需要給每個插槽指定名字

1.2 使用具名插槽和默認插槽

<slot> 元素可以用一個特殊的特性 name 來進一步配置如何分發(fā)內(nèi)容。多個插槽可以有不同的名字曲秉。具名插槽將匹配內(nèi)容片段中有對應 slot 特性的元素镜悉。

未使用name屬性的slot插槽被稱匿名插槽, 也可以叫做默認插槽. 我們在子組件中仍然可以有一個匿名插槽谍珊,作為找不到匹配的內(nèi)容片段的備用插槽。如果沒有默認插槽蛤铜,這些找不到匹配的內(nèi)容片段將被拋棄。

使用具名操作重寫上面的示例:

<div id="app">
     <!-- 使用組件 -->
     <my-child >
         <h2 slot="title">這是一篇介紹vue插槽的文章</h2>

         <p>這是文章的第一段</p>
         <p>這是文章的第二段內(nèi)容</p>
         <p>這是文章的第三段內(nèi)容</p>

         <span slot="time">2020年5月1日</span>
     </my-child>

</div>

<!-- 組件模板 -->
<template id="mychild">
    <div class="article">
        <div class="title">
            <slot name="title">這里是標題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時間的插槽</slot>
        </div>
    </div>
</template>

<script>

    //  組件選項對象
    let MyChild = {
        template: `#mychild`
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        components: {
            MyChild
        }
    })
</script>

結(jié)果:

image

此時我們就會發(fā)現(xiàn),分發(fā)的內(nèi)容以及正常插入到對應的插槽上了

通過上面的例子我們就知道了,slot如果沒有顯示的使用name屬性指定插槽的名字,那么slot默認有個名字default,默認插槽,如果在分發(fā)內(nèi)容時,沒有指定插槽,所有的內(nèi)容都將默認插到默認插槽上

2. 作用域插槽

2.1 作用插槽的理解和使用

通過學習我們知道,插槽的內(nèi)容最后是在子組件模板上渲染的, 那么就會在有得時候需要在分發(fā)的內(nèi)容中使用子組件中才有的數(shù)據(jù),怎么辦呢. 這個時候就要用到作用域插槽了

作用域插槽是一種特殊類型的插槽迷雪,用作一個 (能被傳遞數(shù)據(jù)的) 可重用模板载矿,來代替已經(jīng)渲染好的元素垄潮。

簡而言之,就是利用slot 標簽將子組件的數(shù)據(jù)傳遞到分發(fā)內(nèi)中上,就像prop傳遞數(shù)據(jù)給組件一樣

在父級中,具有特殊特性 slot-scope<template> 元素必須存在闷盔,表示它是作用域插槽的模板弯洗。slot-scope 的值將被用作一個臨時變量名,此變量接收從子組件傳遞過來的 props 對象:

示例:

<div id="app">
     <!-- 使用組件 -->
     <my-child >
         <template slot-scope="props">
            <button>{{ props.text }}</button>
         </template>
     </my-child>

</div>

<!-- 組件模板 -->
<template id="mychild">
    <div>
        <slot :text="text"></slot>
    </div>
</template>

<script>
    //  組件選項對象
    let MyChild = {
        template: `#mychild`,
        data(){
            return {
                text: "提交"
            }
        }
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        components: {
            MyChild
        }
    })

</script>

在 2.5.0+逢勾,slot-scope 能被用在任意元素或組件中而不再局限于 <template>牡整。

也就意味著可以如下寫法

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <button slot-scope="props">{{ props.text }}</button>
    </my-child>
</div>

顯示結(jié)果

image
2.2 作用域插槽也可以使用解構(gòu)寫法
<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <button slot-scope="{text}">{{ text }}</button>
    </my-child>
</div>

很遺憾的告訴你, 具名插槽和作用域插槽的用法在未來即將被廢棄?

What? 那么我們怎么處理具名插槽和作用域插槽取消后留下的問題呢? 不用擔心,往下看.

3. v-slot指令

v-slot 指令自 Vue 2.6.0 起被引入,提供更好的支持 slotslot-scope attribute 的 API 替代方案溺拱。v-slot 完整的由來參見這份 RFC逃贝。在接下來所有的 2.x 版本中 slotslot-scope attribute 仍會被支持,但已經(jīng)被官方廢棄且不會出現(xiàn)在 Vue 3 中迫摔。

3.1 使用v-slot處理具名插槽的問題

在向具名插槽提供內(nèi)容的時候沐扳,我們可以在一個 <template> 元素上使用 v-slot 指令,并以 v-slot 的參數(shù)的形式提供其名稱:

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <template v-slot:title>
            <h2>這是一篇介紹vue插槽的文章</h2>
        </template>

        <p>這是文章的第一段</p>
        <p>這是文章的第二段內(nèi)容</p>
        <p>這是文章的第三段內(nèi)容</p>

        <template v-slot:time>
            <span>2020年5月1日</span>
        </template>
    </my-child>

</div>

<!-- 組件模板 -->
<template id="mychild">
    <div class="article">
        <div class="title">
            <slot name="title">這里是標題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時間的插槽</slot>
        </div>
    </div>
</template>

<script>

    //  組件選項對象
    let MyChild = {
        template: `#mychild`
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        components: {
            MyChild
        }
    })
</script>

顯示結(jié)果:

image

現(xiàn)在 <template> 元素中的所有內(nèi)容都將會被傳入相應的插槽句占。任何沒有被包裹在帶有 v-slot<template> 中的內(nèi)容都會被視為默認插槽的內(nèi)容迫皱。

如果你希望更明確一些,仍然可以在一個 <template> 中包裹默認插槽的內(nèi)容:

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <template v-slot:title>
            <h2>這是一篇介紹vue插槽的文章</h2>
        </template>

        <template v-slot:default>
            <p>這是文章的第一段</p>
            <p>這是文章的第二段內(nèi)容</p>
            <p>這是文章的第三段內(nèi)容</p>
        </template>

        <template v-slot:time>
            <span>2020年5月1日</span>
        </template>
    </my-child>

</div>

注意 v-slot 只能添加在 <template> 上

3.2 使用v-slot處理作用域插槽的問題

綁定在 <slot> 元素上的 attribute 被稱為插槽 prop∠街冢現(xiàn)在在父級作用域中,我們可以使用帶值的 v-slot 來定義我們提供的插槽 prop 的名字:

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <template v-slot:default="props">
            <button>{{ props.text }}</button>
        </template>
    </my-child>
</div>

<!-- 組件模板 -->
<template id="mychild">
    <div>
        <slot :text="text"></slot>
    </div>
</template>

<script>
    //  組件選項對象
    let MyChild = {
        template: `#mychild`,
        data(){
            return {
                text: "提交"
            }
        }
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        components: {
            MyChild
        }
    })

</script>

顯示結(jié)果

image
3.3 作用域插槽的特殊處理

在上述情況下和敬,當被提供的內(nèi)容只有默認插槽時凹炸,組件的標簽才可以被當作插槽的模板來使用。這樣我們就可以把 v-slot 直接用在組件上:

<div id="app">
     <!-- 使用組件 -->
     <my-child v-slot:default="props">
            <button>{{ props.text }}</button>
     </my-child>
</div>

這種寫法還可以更簡單昼弟。就像假定未指明的內(nèi)容對應默認插槽一樣啤它,不帶參數(shù)的 v-slot 被假定對應默認插槽:

<div id="app">
     <!-- 使用組件 -->
     <my-child v-slot="props">
            <button>{{ props.text }}</button>
     </my-child>
</div>

這用這種簡單語法的情況就是在組件中只有一個默認插槽,一但有多個插槽,請使用完整的語法

4. 動態(tài)插槽

2.6.0 新增

動態(tài)指令參數(shù)也可以用在 v-slot 上,來定義動態(tài)的插槽名:

還是以我們剛才文章的那個多插槽為例;

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <template v-slot:[head]>
            <h2>這是一篇介紹vue插槽的文章</h2>
        </template>

        <p>這是文章的第一段</p>
        <p>這是文章的第二段內(nèi)容</p>
        <p>這是文章的第三段內(nèi)容</p>

        <template v-slot:[food]>
            <span>2020年5月1日</span>
        </template>
    </my-child>

</div>

<!-- 組件模板 -->
<template id="mychild">
    <div class="article">
        <div class="title">
            <slot name="title">這里是標題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時間的插槽</slot>
        </div>
    </div>
</template>

<script>

    //  組件選項對象
    let MyChild = {
        template: `#mychild`
    };

    //  實例中注冊組件
    const vm = new Vue({
        el:"#app",
        data:{
            head:"title",
            food:"time"
        },
        components: {
            MyChild
        }
    })
</script>

此時template 標簽上的v-solt指令參數(shù)是一個中括號, 中括號里的值將是一個變量,為當前父組件的數(shù)據(jù)

5. 具名插槽的縮寫

2.6.0 新增

v-onv-bind 一樣,v-slot 也有縮寫变骡,即把參數(shù)之前的所有內(nèi)容 (v-slot:) 替換為字符 #离赫。例如 v-slot:header 可以被重寫為 #header

<div id="app">
    <!-- 使用組件 -->
    <my-child >
        <template #title>
            <h2>這是一篇介紹vue插槽的文章</h2>
        </template>

        <p>這是文章的第一段</p>
        <p>這是文章的第二段內(nèi)容</p>
        <p>這是文章的第三段內(nèi)容</p>

        <template #time>
            <span>2020年5月1日</span>
        </template>

    </my-child>

</div>

然而,和其它指令一樣塌碌,該縮寫只在其有參數(shù)的時候才可用渊胸。這意味著以下語法是無效的:

<my-child >
    <!-- 這種寫法無效 -->
    <template #="props">
        <h2>這是一篇介紹vue插槽的文章</h2>
    </template>
</my-child>

如果你希望使用縮寫的話,你必須始終以明確插槽名取而代之:

<my-child >
    <!-- 這種寫法有效,因為有指令參數(shù) -->
    <template #deatule="props">
        <h2>這是一篇介紹vue插槽的文章</h2>
    </template>
</my-child>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末台妆,一起剝皮案震驚了整個濱河市翎猛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌接剩,老刑警劉巖切厘,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懊缺,居然都是意外死亡疫稿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門鹃两,熙熙樓的掌柜王于貴愁眉苦臉地迎上來遗座,“玉大人,你說我怎么就攤上這事怔毛≡逼迹” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵拣度,是天一觀的道長碎绎。 經(jīng)常有香客問我,道長抗果,這世上最難降的妖魔是什么筋帖? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮冤馏,結(jié)果婚禮上日麸,老公的妹妹穿的比我還像新娘。我一直安慰自己逮光,他們只是感情好代箭,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涕刚,像睡著了一般嗡综。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上杜漠,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天极景,我揣著相機與錄音察净,去河邊找鬼。 笑死盼樟,一個胖子當著我的面吹牛氢卡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晨缴,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼译秦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喜庞?” 一聲冷哼從身側(cè)響起诀浪,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎延都,沒想到半個月后雷猪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡晰房,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年求摇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殊者。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡与境,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猖吴,到底是詐尸還是另有隱情摔刁,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布海蔽,位于F島的核電站共屈,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏党窜。R本人自食惡果不足惜拗引,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幌衣。 院中可真熱鬧矾削,春花似錦、人聲如沸豁护。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楚里。三九已至挡逼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腻豌,已是汗流浹背家坎。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吝梅,地道東北人虱疏。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像苏携,于是被迫代替她去往敵國和親做瞪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容