閱讀之前
本文主要參照了Vue官方文檔的插槽部分說(shuō)明,中間加入的自己的理解旅择,寫的比較簡(jiǎn)潔易懂沽一。各位看官可以對(duì)照官方文檔和本文的介紹來(lái)理解slot插槽語(yǔ)法秘案。
Vue 插槽(2.60版本以后)
插槽可以讓通用組件更加多樣化,它類似React中的children莫鸭。
聲明:以下所有內(nèi)容以父級(jí)(通用)組件和應(yīng)用(調(diào)用)組件的關(guān)系舉例說(shuō)明闹丐。
-
最簡(jiǎn)單的使用
比如你想聲明一個(gè)帶有特殊border的div作為一個(gè)通用組件BorderedDiv。
<template>
<div class="some-border-class">
// 這里是包裹的不同的內(nèi)容
// 可能你很想使用this.props.children(如果你曾是React使用者)
</div>
</template>
在使用該組件時(shí)
<bordered-div>
<p>被包裹的文字</p>
</bordered-div>
這時(shí)你會(huì)想到:這個(gè)文字如何傳遞給父級(jí)組件呢被因?
直接這樣寫就好:
<template>
<div class="some-border-class">
// 這里是包裹的不同的內(nèi)容
<slot></slot>
</div>
</template>
-
作用域
<common-component :data="[1,2,3]">
{{ data }}
<!--
這里的 `data` 會(huì)是 undefined卿拴,因?yàn)閿?shù)組是 **傳遞給**
<common-component> 的而不是 在 <common-component> 組件
**內(nèi)部**定義的
-->
</common-component >
父級(jí)模板里的所有內(nèi)容都是在父級(jí)作用域中編譯的;子模板里的所有內(nèi)容都是在子作用域中編譯的梨与。
簡(jiǎn)單來(lái)說(shuō):你不能在寫children的時(shí)候直接使用父級(jí)組件中的數(shù)據(jù)堕花,考慮當(dāng)前環(huán)境。
-
后備內(nèi)容
在<slot></slot>標(biāo)簽中的內(nèi)容將在沒(méi)有匹配到插槽內(nèi)容時(shí)渲染
<slot>如果沒(méi)有children粥鞋,我就會(huì)渲染</slot>
如果父級(jí)模板中聲明了插槽缘挽,但是應(yīng)用組件卻沒(méi)有包裹任何內(nèi)容,它便會(huì)渲染為備用內(nèi)容呻粹。
-
具名
可以給<slot></slot> 傳遞name屬性
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot name="default"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
然后這樣向?qū)?yīng)的插槽傳遞內(nèi)容:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
// 可以不用包裹template 直接傳遞給default slot
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
其中:<template v-slot:default>父節(jié)點(diǎn)可以省略壕曼。
注意:
v-slot指令只能使用在<template>上,除非只需要傳遞默認(rèn)插槽等浊。(也就是你的父級(jí)模板中只有一個(gè)沒(méi)有name屬性的插槽)
這時(shí)它可以用在父組件上腮郊。
盡管如此,它也只是<template v-slot:default></template>的縮寫凿掂。
在傳遞多個(gè)插槽時(shí)伴榔,還是需要使用完整的語(yǔ)法。
-
作用域插槽
在通用組件中聲明的模板如下:
<span>
// 給slot聲明了一個(gè)屬性
// 該屬性可以在對(duì)應(yīng)的插槽內(nèi)容中訪問(wèn)
// 省略了 name = "default"
<slot v-bind:user="user"></slot>
</span>
在應(yīng)用組件中:
<common-component>
<!-- v-slot是v-slot:default的縮寫 -->
<template v-slot="slotProps">
// 插槽上聲明的user可以這樣訪問(wèn)
{{ slotProps.user.name }}
</template>
</common-component>
在“裝載插槽”時(shí)庄萎,slot上聲明的屬性綁定的數(shù)據(jù)會(huì)以函數(shù)的參數(shù)形式傳遞給插槽
function (slotProps) {
// 插槽的內(nèi)容
}
因此可以在編寫插槽內(nèi)容時(shí)獲取到common-component(父組件)中的數(shù)據(jù)踪少。
由于slotProps是以函數(shù)參數(shù)的形式傳遞的,因此各種簡(jiǎn)寫也就可以理解了糠涛。
// 解構(gòu)傳參
<template v-slot:default="{ user }">
{{ user.name }}
</template>
// 重命名
<template v-slot:default="{ user: person }" >
{{ person.name }}
</template>
// 默認(rèn)值
<template v-slot:default="{ user={ firstname: 'test' } }">
{{ user.name }}
</template>
-
縮寫
在向具名(聲明了name屬性的)插槽傳遞內(nèi)容時(shí)援奢,(應(yīng)用組件中)可以使用縮寫:
<common-layout>
// 等同于:v-slot:header
<template #header>
// 以下模板內(nèi)容會(huì)傳遞給name = header的插槽
<p>this is header</p>
</template>
// 注意: 不可以 直接#
<template #default>
// 以下內(nèi)容會(huì)傳遞給沒(méi)有聲明name的插槽,也就是默認(rèn)插槽
<p>this is default slot</p>
</template>
</common-layout>
當(dāng)然如果common-layout模板中如果只有一個(gè)默認(rèn)插槽的話忍捡,你可以直接這樣做:
// 相當(dāng)于: v-slot:default="slotProps"
// default不可省略,否則引發(fā)警告
<common-layout #default="slotProps">
{{ slotProps.user.name }}
</common-layout>
-
其他示例
請(qǐng)先看官方給出的示例:todoList示例
關(guān)鍵點(diǎn):
通用組件中這樣聲明:
<!--
我們?yōu)槊總€(gè) todo 準(zhǔn)備了一個(gè)插槽集漾, 將 `todo` 對(duì)象作為一個(gè)
插槽的 prop 傳入.
-->
<slot name="todo" v-bind:todo="todo">
<!-- 后備內(nèi)容 -->
{{ todo.text }}
</slot>
應(yīng)用組件中這樣使用:
<todo-list v-bind:todos="todos">
// 或者簡(jiǎn)寫為: #todo
<template v-slot:todo="{ todo }">
<span v-if="todo.isComplete">?</span>
{{ todo.text }}
</template>
</todo-list>
這樣使用就將li中的內(nèi)容動(dòng)態(tài)化切黔。
- 理解
slot的基本用法簡(jiǎn)單來(lái)說(shuō)就是(我的理解):
在你聲明一個(gè)通用的組件時(shí),將通用的部分聲明為模板具篇,動(dòng)態(tài)的內(nèi)容纬霞,也就是各個(gè)應(yīng)用組件不一致的地方,或者說(shuō)可能需要?jiǎng)討B(tài)渲染的部分聲明為插槽slot驱显,并給該插槽定義name,prop诗芜,以方便應(yīng)用組件獲取數(shù)據(jù)和對(duì)號(hào)入座。
參考:
Vue官方文檔: https://cn.vuejs.org/v2/guide/components-slots.html