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


1. 具名插槽

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

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

需求如下:

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

示例代碼如下:

<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>
    //  組件選項(xiàng)對象
    let MyChild = {
        template: `#mychild`
    };

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

結(jié)果:

具名插槽.png

示例結(jié)果說明:

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

這個(gè)時(shí)候我們就需要給每個(gè)插槽指定名字


1.2 使用具名插槽和默認(rèn)插槽

<slot> 元素可以用一個(gè)特殊的特性 name 來進(jìn)一步配置如何分發(fā)內(nèi)容。多個(gè)插槽可以有不同的名字紧卒。具名插槽將匹配內(nèi)容片段中有對應(yīng) slot 特性的元素屡萤。

未使用name屬性的slot插槽被稱匿名插槽, 也可以叫做默認(rèn)插槽. 我們在子組件中仍然可以有一個(gè)匿名插槽箩兽,作為找不到匹配的內(nèi)容片段的備用插槽拭宁。如果沒有默認(rèn)插槽还栓,這些找不到匹配的內(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">這里是標(biāo)題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認(rèn)插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時(shí)間的插槽</slot>
        </div>
    </div>
</template>

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

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

結(jié)果:

具名插槽2.png

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

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


2. 作用域插槽

2.1 作用插槽的理解和使用

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

作用域插槽是一種特殊類型的插槽,用作一個(gè) (能被傳遞數(shù)據(jù)的) 可重用模板蒲祈,來代替已經(jīng)渲染好的元素甘萧。

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


在父級中,具有特殊特性 slot-scope<template> 元素必須存在梆掸,表示它是作用域插槽的模板扬卷。slot-scope 的值將被用作一個(gè)臨時(shí)變量名,此變量接收從子組件傳遞過來的 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>
    //  組件選項(xiàng)對象
    let MyChild = {
        template: `#mychild`,
        data(){
            return {
                text: "提交"
            }
        }
    };
   
    //  實(shí)例中注冊組件
    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é)果

作用域插槽.png


2.2 作用域插槽也可以使用解構(gòu)寫法

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


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

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


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)容的時(shí)候入挣,我們可以在一個(gè) <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">這里是標(biāo)題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認(rèn)插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時(shí)間的插槽</slot>
        </div>
    </div>
</template>

<script>

    //  組件選項(xiàng)對象
    let MyChild = {
        template: `#mychild`
    };

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

顯示結(jié)果:

v-slot指令處理具名插槽的功能.png

現(xiàn)在 <template> 元素中的所有內(nèi)容都將會被傳入相應(yīng)的插槽硝拧。任何沒有被包裹在帶有 v-slot<template> 中的內(nèi)容都會被視為默認(rèn)插槽的內(nèi)容径筏。


如果你希望更明確一些,仍然可以在一個(gè) <template> 中包裹默認(rèn)插槽的內(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>
    //  組件選項(xiàng)對象
    let MyChild = {
        template: `#mychild`,
        data(){
            return {
                text: "提交"
            }
        }
    };

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

</script>

顯示結(jié)果

v-slot處理作用域插槽功能.png


3.3 作用域插槽的特殊處理

在上述情況下,當(dāng)被提供的內(nèi)容只有默認(rèn)插槽時(shí)咸这,組件的標(biāo)簽才可以被當(dāng)作插槽的模板來使用夷恍。這樣我們就可以把 v-slot 直接用在組件上:

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

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

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

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


4. 動態(tài)插槽

2.6.0 新增

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

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

<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">這里是標(biāo)題內(nèi)容的插槽</slot>
        </div>
        <div class="contont">
            <slot>這里是默認(rèn)插槽</slot>
        </div>
        <div class="time">
            <slot name="time">這里是時(shí)間的插槽</slot>
        </div>
    </div>
</template>

<script>

    //  組件選項(xiàng)對象
    let MyChild = {
        template: `#mychild`
    };

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

此時(shí)template 標(biāo)簽上的v-solt指令參數(shù)是一個(gè)中括號, 中括號里的值將是一個(gè)變量,為當(dāng)前父組件的數(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ù)的時(shí)候才可用醋安。這意味著以下語法是無效的:

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

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

<my-child >
    <!-- 這種寫法有效,因?yàn)橛兄噶顓?shù) -->
    <template #deatule="props">
        <h2>這是一篇介紹vue插槽的文章</h2>
    </template>
</my-child>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吓揪,隨后出現(xiàn)的幾起案子亲怠,更是在濱河造成了極大的恐慌,老刑警劉巖柠辞,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件团秽,死亡現(xiàn)場離奇詭異,居然都是意外死亡叭首,警方通過查閱死者的電腦和手機(jī)习勤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焙格,“玉大人图毕,你說我怎么就攤上這事【彀Γ” “怎么了予颤?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長厢破。 經(jīng)常有香客問我荣瑟,道長,這世上最難降的妖魔是什么摩泪? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮劫谅,結(jié)果婚禮上见坑,老公的妹妹穿的比我還像新娘。我一直安慰自己捏检,他們只是感情好荞驴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著贯城,像睡著了一般熊楼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上能犯,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天鲫骗,我揣著相機(jī)與錄音犬耻,去河邊找鬼。 笑死执泰,一個(gè)胖子當(dāng)著我的面吹牛枕磁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播术吝,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼计济,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了排苍?” 一聲冷哼從身側(cè)響起沦寂,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淘衙,沒想到半個(gè)月后传藏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡幔翰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年漩氨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遗增。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叫惊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出做修,到底是詐尸還是另有隱情霍狰,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布饰及,位于F島的核電站蔗坯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏燎含。R本人自食惡果不足惜宾濒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望屏箍。 院中可真熱鬧绘梦,春花似錦、人聲如沸赴魁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽颖御。三九已至榄棵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背疹鳄。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工拧略, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尚辑。 一個(gè)月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓辑鲤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杠茬。 傳聞我的和親對象是個(gè)殘疾皇子月褥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353