vue插槽slot理解

vue的插槽用法,官方文檔寫的內(nèi)容個(gè)人感覺有點(diǎn)亂,不自己梳理一下的話,使用的時(shí)候也容易懵逼,下面是我對(duì)vue插槽使用的理解:

1.概念

slot概念源于web components規(guī)范草案(地址:https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Slots-Proposal.md
vue官網(wǎng)關(guān)于插槽的文檔中藕赞,第一句話即說明了vue的slot插槽設(shè)計(jì)源于web components,具體內(nèi)容可以自行了解卖局,這里只說vue框架下slot的用法斧蜕。

概念:slot可將父組件子組件標(biāo)簽里寫的content渲染到子組件對(duì)應(yīng)的地方


2.用法

先說通用性用法,再說特殊情況會(huì)讓人比較容易接受砚偶。這里以最具通用性的寫法批销,以具名插槽的寫法為例子展開
父組件中:

<script>
...
</script>

<template> // 注意這個(gè)template是組件的template屬性,不要跟下面的template標(biāo)簽弄混
  <todo-item>
    <template v-slot:default> // 注意v-slot指令大多數(shù)情況都是寫在template標(biāo)簽里染坯,有一種特殊情況在下一節(jié)會(huì)說到均芽,即使不懂特殊情況也不會(huì)妨礙到使用。
      這里的內(nèi)容會(huì)渲染到子組件對(duì)應(yīng)的地方
    </template>
  </todo-item>
</template>

<style>
...
</style>

子組件中

<div>
  // 子組件中slot標(biāo)簽的name屬性值與父組件中的v-slot綁定的屬性值一致单鹿,形成對(duì)應(yīng)關(guān)系
  <slot name="default"></slot>
</div>

渲染結(jié)果:

<div>
  這里的內(nèi)容會(huì)渲染到子組件對(duì)應(yīng)的地方
</div>

父組件template標(biāo)簽上的v-slot指令與子組件的slot標(biāo)簽的name屬性掀宋,通過綁定一樣的值,形成一一對(duì)應(yīng)的關(guān)系仲锄。
父組件中:

<子組件標(biāo)簽>
  <template v-slot:default>
    我會(huì)渲染到name=default的slot中
  </template>

  <template v-slot:test1>
    我會(huì)渲染到name=test1的slot中
  </template>

  <template v-slot:test2>
    我會(huì)渲染到name=test2的slot中
  </template>
</子組件標(biāo)簽>

子組件中:

<div>
  <slot name="default"></slot> // 我會(huì)渲染到name=default的slot中
</div>

<div>
  <slot name="test1"></slot> // 我會(huì)渲染到name=test1的slot中
</div>

<div>
  <slot name="test2"></slot> // 我會(huì)渲染到name=test2的slot中
</div>

注意劲妙,上述例子中,都有v-slot綁定default屬性的情況儒喊,這里需要說明下镣奋,vue中的插槽用法,default屬性的模板和插槽存在特殊的對(duì)應(yīng)情況怀愧,而比較容易混亂的點(diǎn)就在這里侨颈,這也是vue官網(wǎng)插槽文檔讓人看得很蒙圈的地方,因?yàn)楣倬W(wǎng)并沒有給我們分區(qū)域的講述通用情況和特殊情況芯义,而是穿插著講哈垢,讓人容易理不清楚關(guān)系。


3.插槽的默認(rèn)值

子組件的slot標(biāo)簽中的值可以寫入內(nèi)容毕贼,這部分內(nèi)容會(huì)在沒有對(duì)應(yīng)的模板內(nèi)容的時(shí)候,作為默認(rèn)值展示
父組件

<todo-item>
  <template v-slot:test1>
  我是模板1
  </template>
</todo-item>

子組件

<div>
  <slot name="test1">
  我是插槽1
  </slot>
</div>
<div>
  <slot name="test2">
  我是插槽2
  </slot>
</div>

渲染結(jié)果

<div>
我是模板1
</div>
<div>
我是插槽2
</div>

4.v-slot指令動(dòng)態(tài)綁定屬性

<script>
export default {
  data() {
    return {
      slotName: 'test1'
    }
  }
}
</script>
<template>
  <todo-item>
    <template v-slot:[slotName]>
    </template>
  </todo-item>
</template>
<style>
</style>

具名插槽的寫法具備通用性蛤奢,學(xué)會(huì)了具名插槽寫法鬼癣,那么插槽的用法已經(jīng)能夠掌握8成了陶贼。下面將展開的是插槽中的特殊對(duì)應(yīng)關(guān)系


5.default模板和插槽中的特殊對(duì)應(yīng)關(guān)系

------------默認(rèn)的default模板和插槽-----------
父組件

<todo-item>
  我是default的內(nèi)容
  <template v-slot:test>
    我會(huì)渲染到name=test的slot標(biāo)簽中
  </template>
  我也是default的內(nèi)容
</todo-item>

子組件情形1

<div>
  <slot></slot>
</div>

子組件情形2

<div>
  <slot name="default"></slot>
</div>

渲染結(jié)果都是

<div>
  我是default的內(nèi)容  我也是default的內(nèi)容
</div>

由于兩種情形中都沒有name屬性是test的插槽,所以渲染結(jié)果中沒有出現(xiàn)test模板里的內(nèi)容待秃。

上述例子中涵蓋了2個(gè)知識(shí)點(diǎn)拜秧,首先通過子組件情形2能得到渲染結(jié)果,可以得出一個(gè)結(jié)論:

①.父組件中只要是不在template里的內(nèi)容章郁,無論內(nèi)容在什么位置(必須在子組件標(biāo)簽里)枉氮,默認(rèn)都是default模板的內(nèi)容,即
<todo-item>
  我是default的內(nèi)容 // 默認(rèn)算default模板內(nèi)容
  <template v-slot:test>
    我會(huì)渲染到name=test的slot標(biāo)簽中
  </template>
  我也是default的內(nèi)容 // 默認(rèn)算default模板內(nèi)容
</todo-item>
等價(jià)于
<todo-item>
  <template v-slot:default>
    我是default的內(nèi)容  我也是default的內(nèi)容
  </template>
  
  <template v-slot:test>
    我會(huì)渲染到name=test的slot標(biāo)簽中
  </template>
</todo-item>

default模板的內(nèi)容必定會(huì)渲染到defalut插槽中暖庄,所以聊替,通過子組件情形1能得出渲染結(jié)果,也可以得出一個(gè)結(jié)論:

②.子組件中沒有指定name屬性的slot標(biāo)簽培廓,默認(rèn)都是default插槽惹悄,即
<div>
  <slot></slot>
</div>
等價(jià)于
<div>
  <slot name="default"></slot>
</div>

最后還需要注意,模板和插槽的對(duì)應(yīng)關(guān)系是1對(duì)多的關(guān)系肩钠。即同名模板只能有一個(gè)泣港,但是同名插槽可以有無數(shù)個(gè),會(huì)同時(shí)渲染

以上內(nèi)容涵蓋了9成的插槽用法价匠,足以滿足日常使用当纱。下面將要對(duì)插槽作用域問題展開講解


6.模板內(nèi)容的作用域和插槽內(nèi)容的作用域

很簡(jiǎn)單
1.模板內(nèi)容一般都是在父組件,所以模板內(nèi)容的作用域自然是父組件的作用域踩窖,父組件的動(dòng)態(tài)內(nèi)容基本上取自父組件的變量或函數(shù)坡氯,但是有特殊情況可以讀取到子組件傳出來的值,第3點(diǎn)會(huì)講毙石。

2.同理廉沮,插槽一般都是在子組件,所以作用域自然在子組件徐矩,比如子組件插槽中放入了動(dòng)態(tài)內(nèi)容作為默認(rèn)值滞时,該動(dòng)態(tài)內(nèi)容必定取值于子組件的變量,也只能讀取到子組件的變量和函數(shù)

3.特殊情況滤灯,父組件可以用子組件傳出來的值坪稽,這個(gè)時(shí)候會(huì)有寫法上的變化:
子組件

<script>
export default {
  data() {
    return {
      content: '我是子組件',
      show: true
    }
  }
}
</script>
<template>
  <div>
    <slot name="default" :todo-item-content="content" :show="show"></slot> // 通過格式:自定義屬性名="變量名"將值傳出
  </div>
</template>
<style>
</style>

父組件正常調(diào)用

<todo-item>
  <template v-slot:default="props"> //這里的props是我們自己定義的名稱鳞骤,你可以自己起任意名窒百,它是一個(gè)對(duì)象,包含子組件傳過來的所有值
    <div> // 這里需要注意的是豫尽,子組件用橫杠屬性名傳過來的值篙梢,在調(diào)用的時(shí)候要用駝峰名調(diào)用
        {{props.todoListContent}}
    </div>
    <div> // 不是橫杠屬性名傳過來的值可以直接調(diào)用
        {{props.show}}
    </div>
  </template>
</todo-item>

父組件解構(gòu)對(duì)象調(diào)用

<todo-item>
  <template v-slot:default="{todoListContent,show}">
    <div>
        {{todoListContent}}
    </div>
    <div>
        {{show}}
    </div>
  </template>
</todo-item>

渲染結(jié)果

<div>
  我是子組件
</div>
<div> 
    true
</div>

7.v-slot指令縮寫

v-slot指令可以變成縮寫的寫法美旧,類似v-bind縮寫為:渤滞,v-on縮寫為@贬墩,v-slot可以縮寫為#
例如

<template v-slot:default>
</template>

<template v-slot:test1>
</template>

<template v-slot:test2>
</template>

等價(jià)于

<template #default>
</template>

<template #test1>
</template>

<template #test2>
</template>

8.default模板一種特殊的接受子組件插槽傳值的寫法(結(jié)合第6點(diǎn)的例子)

<todo-item #default="{todoListContent,show}">
  <div>
      {{todoListContent}}
  </div>
  <div>
      {{show}}
  </div>
</todo-item>

這里出現(xiàn)了v-slot指令直接綁定在子組件標(biāo)簽名上的情況妄呕,使用場(chǎng)景是陶舞,當(dāng)前模板只有一個(gè)default模板,并且需要獲取子組件傳來的值時(shí)绪励,才能這樣使用肿孵。

不接受傳值的情況,會(huì)報(bào)錯(cuò)

<todo-item #default> // 報(bào)錯(cuò)疏魏,必須是接受傳值的寫法停做,即#default="xxx.."
  <div>
      我是模板
  </div>
</todo-item>

非default模板,也會(huì)報(bào)錯(cuò)
子組件

<script>
export default {
  data() {
    return {
      content: '我是子組件'蠢护,
      show: true
    }
  }
}
</script>
<template>
  <div> // 這里是test插槽
    <slot name="test" :todo-item-content="content" :show="show"></slot> 
  </div>
</template>
<style>
</style>

父組件

// 這里是test模板雅宾,是具名模板的寫法,會(huì)報(bào)錯(cuò)葵硕,因?yàn)檫@種寫法只支持default模板
<todo-item #test="{todoListContent眉抬,show}"> 
  <div>
      {{todoListContent}}
  </div>
  <div>
      {{show}}
  </div>
</todo-item>

除了default模板外,還存在其他模板時(shí)懈凹,也會(huì)報(bào)錯(cuò)

<todo-item #default="{todoListContent蜀变,show}"> // default模板
  <div>
      {{todoListContent}}
  </div>
  <div>
      {{show}}
  </div>
  <template v-slot:test> // test模板  此處將不生效,并且會(huì)拋出警告
  </template>
</todo-item>

結(jié)語(yǔ):

以上基本總結(jié)了插槽的所有用法介评,其中第5點(diǎn)和第8點(diǎn)的特殊情況都是針對(duì)default模板的库北,這一點(diǎn)一定要分清楚。

還有1點(diǎn)很關(guān)鍵的知識(shí)们陆,即default模板和插槽不算是具名模板和插槽寒瓦,第8點(diǎn)的非default模板會(huì)報(bào)錯(cuò)的原因,即該特殊情況不支持具名模板和插槽坪仇。但是default模板和插槽在平時(shí)寫的時(shí)候可以用具名模板和插槽的寫法杂腰,也可以用省略的寫法,即第5點(diǎn)描述的情況椅文。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喂很,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子皆刺,更是在濱河造成了極大的恐慌少辣,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羡蛾,死亡現(xiàn)場(chǎng)離奇詭異漓帅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門忙干,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屯伞,“玉大人,你說我怎么就攤上這事豪直。” “怎么了珠移?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵弓乙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我钧惧,道長(zhǎng)暇韧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任浓瞪,我火速辦了婚禮懈玻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乾颁。我一直安慰自己涂乌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布英岭。 她就那樣靜靜地躺著湾盒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪诅妹。 梳的紋絲不亂的頭發(fā)上罚勾,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音吭狡,去河邊找鬼尖殃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛划煮,可吹牛的內(nèi)容都是我干的送丰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼般此,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼铐懊!你這毒婦竟也來了壁畸?” 一聲冷哼從身側(cè)響起太抓,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤掉丽,失蹤者是張志新(化名)和其女友劉穎捶障,沒想到半個(gè)月后示绊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摄杂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年映挂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扣蜻。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莽使,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笙僚,到底是詐尸還是另有隱情芳肌,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布肋层,位于F島的核電站庇勃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏槽驶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一鸳兽、第九天 我趴在偏房一處隱蔽的房頂上張望掂铐。 院中可真熱鬧,春花似錦揍异、人聲如沸全陨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辱姨。三九已至,卻和暖如春戚嗅,著一層夾襖步出監(jiān)牢的瞬間雨涛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工懦胞, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留替久,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓躏尉,卻偏偏與公主長(zhǎng)得像蚯根,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胀糜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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