vuejs中的默認(rèn)插槽-具名插槽-作用域插槽三者的比較

前言

Vue中的插槽是一個(gè)非常強(qiáng)大的功能,在復(fù)用組件模塊的時(shí)候,針對(duì)相似的結(jié)構(gòu),擁有不通的內(nèi)容時(shí),使用插槽就非常方便,一定程度上可以減少在模板中使用大量的邏輯判斷,控制顯示不通的內(nèi)容

同時(shí),也可以讓代碼組織結(jié)構(gòu)更加清晰,雖然使用上是簡(jiǎn)單了,但是插槽有些不是很好理解俐筋,不是很直觀

它是讓父組件可以向子組件指定位置處插入一html結(jié)構(gòu),自由靈活,也是組件間的一種通信方式

形式上有,默認(rèn)插槽,具名插槽還有作用域插槽

大家在使用element-ui表格的時(shí)候,雖然都知道怎么用,表頭,以及內(nèi)容模板的渲染,就使用了插槽,但是往往是很迷糊的

因?yàn)楸怀橄罅说?/p>

今天就一起來(lái)學(xué)習(xí)下,學(xué)完之后,在看element-ui表格的時(shí)候,希望能給你帶來(lái)一些啟發(fā),下次再次使用時(shí),理解更上一層樓

01-示例.png

默認(rèn)插槽

官方文檔里介紹到:Vue 實(shí)現(xiàn)了一套內(nèi)容分發(fā)的 API厂镇,這套 API 的設(shè)計(jì)靈感源自 Web Components規(guī)范草案,將 <slot>元素作為承載分發(fā)內(nèi)容的出口

這句話不是很好理解,換句話說(shuō),也就是,<slot>可以充當(dāng)元素標(biāo)簽的占位符,可以代替在父組件引用的組件內(nèi)的html標(biāo)簽內(nèi)容

以如下示例所示

在App組件中引入SlotBase.vue組件

<template>
  <div id="app">
     <SlotBase
              :lists="lists">
             <p>默認(rèn)內(nèi)容</p>
     </SlotBase>
  </div>
</template>

<script>

import SlotBase from "./components/SlotBase.vue"

export default {
  name: 'App',
  components: {
    SlotBase
  },
  data() {
    return {
      lists: [
        {
          id: "001",
          title: "直播賣酒"
        },
        {
          id: "002",
          title: "直播打賞"
        },
        {
          id: "003",
          title: "直播炫富"
        }
      ]
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

而在編寫(xiě)SlotBase.vue組件中,引入slot標(biāo)簽,如下所示

<template>
    <div class="wrap">
        <div class="list" v-for="list in lists" :key="list.id">
            {{list.title}}
            <!-- 此處引入slot標(biāo)簽 -->
            <slot></slot>
        </div>
    </div>
</template>

<script>
    export default {
        name: "SlotBase",
        props: {
            lists: {
                type: Array
            }
        },
        mounted() {
            console.log(this.lists);
        }
    }
</script>

<style lang="scss" scoped>
.wrap {
    display: flex;
    justify-content: center;
}
.list {
    width: 400px;
    height: 200px;
    border:1px solid red;
    margin-right: 10px;
}
</style>

在子組件內(nèi)的<slot></slot>標(biāo)簽就是插槽,代替了在父組件內(nèi)的<p>默認(rèn)內(nèi)容</p>

如果你在父組件的自定義標(biāo)簽內(nèi),插入了html模板,在子組件沒(méi)有使用slot,那么父組件內(nèi)插入的標(biāo)簽內(nèi)容是不會(huì)被插入進(jìn)去的

現(xiàn)在知道插槽是什么了吧,可以在組件標(biāo)簽內(nèi)定義需要的內(nèi)容冲簿,通過(guò)插槽加入到組件內(nèi)部中

組件內(nèi)部的<slot></slot>元素就好像一個(gè)傳送門(mén)锣夹,也就是所謂的槽浪南,它提供了內(nèi)容的入口父款,也決定了內(nèi)容的位置浅役。 組件標(biāo)簽中定義的內(nèi)容斩松,通過(guò)這個(gè)“傳送門(mén)”就可以加入到組件內(nèi)部中

插槽中的“插件”就是組件標(biāo)簽中的內(nèi)容。

插槽中的“槽”就是在組件中的<slot></slot>元素,當(dāng)沒(méi)有<slot></slot>元素的時(shí)候觉既,就不渲染組件標(biāo)簽中的內(nèi)容

當(dāng)是默認(rèn)插槽時(shí),我們可以使用template標(biāo)簽給包裹起來(lái)的,并且在上面添加v-slot:default屬性,這代表的是默認(rèn)插槽

<template v-slot:default>
    <p>默認(rèn)內(nèi)容</p>
</template>

具名插槽

如果要將不通的內(nèi)容放在不通的位置,那么默認(rèn)插槽就無(wú)法辦到了

顧名思義,具名插槽,就是給插槽定義一個(gè)名字,讓每個(gè)不通的模板對(duì)應(yīng)著不通的名字

我們給在父組件內(nèi)的插入的模板屬性上添加v-slot:插槽名字,而在子組件內(nèi)通過(guò)添加name屬性<slot name="插槽名字"></slot>

需要注意的是,name的值需要與v-slot的值要一一對(duì)應(yīng),如果對(duì)不上的話,那么就會(huì)達(dá)不到我們預(yù)期的效果

如下示例代碼所示:在App父組件中

<template>
  <div id="app">
     <SlotBase
              :lists="lists">
             <template v-slot:default>
               <p>默認(rèn)內(nèi)容</p>
             </template>
             <template v-slot:content>
                   <p>我是直播賣酒-content</p>
             </template>
              <!-- <template v-slot:content2>
                   <p>我是直播打賞-content</p>
             </template> -->
             <!-- 可以簡(jiǎn)寫(xiě)成如下所示 -->
              <template #content2>
                   <p>我是直播打賞-content</p>
             </template>
     </SlotBase>
  </div>
</template>

<script>

import SlotBase from "./components/SlotBase.vue"

export default {
  name: 'App',
  components: {
    SlotBase
  },
  data() {
    return {
      lists: [
        {
          id: "001",
          title: "直播賣酒",
        },
        {
          id: "002",
          title: "直播打賞"
        },
        {
          id: "003",
          title: "直播炫富"
        }
      ]
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

而在子組件,slotBase.vue

<template>
    <div class="wrap">
        <div class="list" v-for="list in lists" :key="list.id">
            {{list.title}}
            <!-- 此處引入slot標(biāo)簽 -->
            <slot></slot>
            <slot name="content" v-if="list.title =='直播賣酒'"></slot>
            <slot name="content2" v-if="list.title =='直播打賞'"></slot>
        </div>
    </div>
</template>

<script>
    export default {
        name: "SlotBase",
        props: {
            lists: {
                type: Array
            }
        },
        mounted() {
            console.log(this.lists);
        }
    }
</script>

<style lang="scss" scoped>
.wrap {
    display: flex;
    justify-content: center;
}
.list {
    width: 400px;
    height: 200px;
    border:1px solid red;
    margin-right: 10px;
}
</style>

上面我用了一個(gè)v-if條件渲染表達(dá)式,我們可以可以根據(jù)一些條件控制元素的顯示和隱藏

上面的具名插槽,在父組件中v-slot:content可以縮寫(xiě)為#content,當(dāng)我們看到這種簡(jiǎn)寫(xiě)的時(shí)候,知道它也是給插槽起一個(gè)具體的名字即可

它跟 v-onv-bind 一樣惧盹,v-slot 也有縮寫(xiě)乳幸,即把參數(shù)之前的所有內(nèi)容 (v-slot:) 替換為字符 #。例如 v-slot:header 可以被重寫(xiě)為 #header

如果你看不懂,那就是對(duì)簡(jiǎn)寫(xiě)插槽的名稱有些陌生了

從上面的示例中,我們可以做出一些總結(jié)

  1. 具名插槽可以根據(jù)名稱渲染對(duì)應(yīng)的html標(biāo)簽?zāi)0鍍?nèi)容
  2. 沒(méi)有定義名稱的內(nèi)容會(huì)被默認(rèn)插槽統(tǒng)一渲染
  3. 默認(rèn)插槽其實(shí)也是一個(gè)具名插槽,名稱為default
  4. 父組件內(nèi)插槽內(nèi)容可以是模板html標(biāo)簽元素,也可以是組件

注意

這個(gè)v-slot只能用在template標(biāo)簽上

舊版本寫(xiě)法

在父組件上使用v-slot:插槽名稱,這個(gè)是vue2.6.0以后的寫(xiě)法,在vue2.6.0之前,可以在模板上使用slot="插槽的名稱"

作用域插槽

相比于默認(rèn)插槽,具名插槽,作用域插槽有些難以理解

如果你理解js中的作用域鏈和Es6中的塊級(jí)作用域,那么對(duì)于銜接作用域插槽,可能會(huì)好些

有時(shí)钧椰,讓插槽內(nèi)容能夠訪問(wèn)子組件中才有的數(shù)據(jù),是很有用的

插槽中內(nèi)容的流動(dòng)方向是從組件標(biāo)簽傳到組件內(nèi)部

作用域插槽則讓作用域反向流動(dòng),從組件內(nèi)部傳到組件標(biāo)簽內(nèi),可以在組件標(biāo)簽內(nèi)訪問(wèn)到組件內(nèi)部的變量粹断,

換而言之,在父組件的模板中,如何拿到子組件傳遞過(guò)來(lái)的數(shù)據(jù),而子組件(插槽)內(nèi)部定義的數(shù)據(jù),如何傳遞到父組件當(dāng)中去

也就是可以通過(guò)作用域插槽傳遞數(shù)據(jù)

我們?cè)?code>slotBase.vue組件中內(nèi)部定義一個(gè)數(shù)據(jù)msg

<template>
    <div class="wrap">
        <div class="list" v-for="list in lists" :key="list.id">
            {{list.title}}
            <!-- 此處引入slot標(biāo)簽 -->
            <slot></slot>
            <!--  v-bind,自定義屬性的方式向slot插槽傳遞了屬性-->
            <slot name="content" 
                  v-if="list.title =='直播賣酒'" 
                  :msg="msg"></slot>
            <slot name="content2" v-if="list.title =='直播打賞'"></slot>
        </div>
    </div>
</template>

<script>
    export default {
        name: "SlotBase",
        props: {
            lists: {
                type: Array
            }
        },
        data() {
            return {
                // 子組件定義的數(shù)據(jù)
                msg: "itclanCoder"
            }
        },
        mounted() {
            console.log(this.lists);
        }
    }
</script>

<style lang="scss" scoped>
.wrap {
    display: flex;
    justify-content: center;
}
.list {
    width: 400px;
    height: 200px;
    border:1px solid red;
    margin-right: 10px;
}
</style>

在上面的代碼中,在slot元素上綁定了msg屬性,這個(gè)attribute被稱為插槽prop

那么在父級(jí)作用域中,又該如何接收子組件傳遞過(guò)來(lái)的數(shù)據(jù)呢

v2.6.0中使用的是v-slot:插槽名="slotProps",其中這個(gè)slotProps是自己任意定義的,名字自己隨意

代碼如下所示:

 <template v-slot:content="slotProps">
    {{slotProps.msg}}
</template>
// 也可以縮寫(xiě)為#插槽名="屬性Props"
 <template #content="slotProps">
    {{slotProps.msg}}
</template>

而在舊版本中,也可以這么寫(xiě)

<template slot="content" slot-scope="slotProps">
        {{slotProps.msg}}
</template>

新版本的寫(xiě)法與vue2.6.0以下的版本不能混寫(xiě),注意,這種廢棄的語(yǔ)法,在vue3.0中不會(huì)出現(xiàn)了的

所以還是用最新的寫(xiě)法吧,但是一些老的vue2.0項(xiàng)目,舊版本的寫(xiě)法,要看的懂的

以上就是默認(rèn)插槽,具名插槽,作用域插槽的使用,插槽是一個(gè)非常強(qiáng)大的功能,在組件的復(fù)用時(shí),對(duì)于復(fù)用結(jié)構(gòu)和精簡(jiǎn)代碼非常有用

如果大家有做過(guò)那種后臺(tái)cms管理系統(tǒng),針對(duì)很多不同種類的各種表單彈窗,而表單彈窗內(nèi),有時(shí)要根據(jù)后端返回的接口props去顯示指定的內(nèi)容

這時(shí)候,插槽就非常有用了

獨(dú)占默認(rèn)插槽的縮寫(xiě)

當(dāng)被提供的內(nèi)容只有默認(rèn)插槽時(shí),組件的標(biāo)簽才可以被當(dāng)做插槽的模板來(lái)使用

我們可以直接把v-slot直接用在組件上

<CurrentUser v-slot:default="slotProps">
          <p>{{slotProps.user}}</p>
</CurrentUser>

還可以在簡(jiǎn)化一下嫡霞。就像假定未指明的內(nèi)容對(duì)應(yīng)默認(rèn)插槽一樣瓶埋,不帶參數(shù)的 v-slot 被假定對(duì)應(yīng)默認(rèn)插槽

<CurrentUser v-slot="slotProps">
          <p>{{slotProps.user}}</p>
</CurrentUser>

需要注意的是,以下寫(xiě)法是不可以的,當(dāng)v-slot用在自定義標(biāo)簽組件上,不能縮寫(xiě)

Named slots must use '<template>' on a custom element

<CurrentUser #slotProps>
          <p>{{slotProps.user}}</p>
</CurrentUser>

::: tip 注意
默認(rèn)插槽的縮寫(xiě)語(yǔ)法不能和具名插槽混用,因?yàn)樗鼤?huì)導(dǎo)致作用域不明確

<!-- 無(wú)效,會(huì)導(dǎo)致警告 -->
<current-user v-slot="slotProps">
  {{ slotProps.user.firstName }}
  <template v-slot:other="otherSlotProps">
    slotProps is NOT available here
  </template>
</current-user>

:::
只要出現(xiàn)多個(gè)插槽,所有的插槽使用完整的基于template的語(yǔ)法
也就是說(shuō),v-slot用在template標(biāo)簽上

<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>

  <template v-slot:other="otherSlotProps">
    ...
  </template>
</current-user>

總結(jié)

以上本節(jié)的內(nèi)容,插槽是一個(gè)非常強(qiáng)大的功能,默認(rèn)插槽在子組件內(nèi)部使用<slot></slot>進(jìn)行占位,而在父組件內(nèi),使用html標(biāo)簽,或者組件

如果子組件使用了多個(gè)插槽诊沪,那么就使用具名插槽對(duì)每個(gè)插槽進(jìn)行區(qū)分,子組件內(nèi)的<slot name="插槽名稱"></slot>,而在父組件中,使用template標(biāo)簽

<template v-slot:插槽名稱></template>,其中v-slot有簡(jiǎn)寫(xiě)#插槽名稱,可以使用在具體的標(biāo)簽上,但是當(dāng)有多個(gè)插槽時(shí),只能用在template標(biāo)簽上

當(dāng)父組件想要拿到子組件中的數(shù)據(jù),子組件內(nèi)部又是如何把內(nèi)部數(shù)據(jù)傳遞到外部組件中去的呢,在子組件內(nèi)部是通過(guò)在slot插槽props傳遞到父父組件當(dāng)中去的

而在父組件當(dāng)中,通過(guò)v-slot:插槽名="slotProps"進(jìn)行接收,這個(gè)slotProps是一個(gè)集合對(duì)象,接收了子組件props

這就是作用域插槽,它也是父子組件傳遞數(shù)據(jù)的一種方式

原文出處-Vuejs中的默認(rèn)插槽养筒、具名插槽,作用域插槽

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市端姚,隨后出現(xiàn)的幾起案子晕粪,更是在濱河造成了極大的恐慌,老刑警劉巖寄锐,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兵多,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡橄仆,警方通過(guò)查閱死者的電腦和手機(jī)剩膘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)盆顾,“玉大人怠褐,你說(shuō)我怎么就攤上這事∧埽” “怎么了奈懒?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)宪巨。 經(jīng)常有香客問(wèn)我磷杏,道長(zhǎng),這世上最難降的妖魔是什么捏卓? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任极祸,我火速辦了婚禮,結(jié)果婚禮上怠晴,老公的妹妹穿的比我還像新娘遥金。我一直安慰自己,他們只是感情好蒜田,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布稿械。 她就那樣靜靜地躺著,像睡著了一般冲粤。 火紅的嫁衣襯著肌膚如雪美莫。 梳的紋絲不亂的頭發(fā)上页眯,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音茂嗓,去河邊找鬼餐茵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛述吸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锣笨,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蝌矛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了错英?” 一聲冷哼從身側(cè)響起入撒,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椭岩,沒(méi)想到半個(gè)月后茅逮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡判哥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年献雅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塌计。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挺身,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锌仅,到底是詐尸還是另有隱情章钾,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布热芹,位于F島的核電站贱傀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏伊脓。R本人自食惡果不足惜府寒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丽旅。 院中可真熱鬧椰棘,春花似錦、人聲如沸榄笙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)茅撞。三九已至帆卓,卻和暖如春巨朦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背剑令。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工糊啡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吁津。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓棚蓄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親碍脏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子梭依,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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