面試官:談談 v-slot 的做用?html
本身先想一分鐘。vue
這篇文章假設你對組件的基礎知識有定義的瞭解,若是你對此還不熟悉,請先閱讀。git
從 vue@2.6.x 開始,Vue 爲具名和範圍插槽引入了一個全新的語法,即咱們今天要講的主角:v-slot
指令。目的就是想統一 slot
和 scope-slot
語法,使代碼更加規範和清晰。既然有新的語法上位,很明顯,slot
和 scope-slot
也將會在 vue@3.0.x
中完全的跟咱們說拜拜了。而從 vue@2.6.0
開始,官方推薦咱們使用 v-slot
來替代後二者。github
咱們來一點一點提及吧。文筆有限,不對之處請留言斧正!面試
在 2.6.0+ 中已棄用瀏覽器
先前,咱們使用具名插槽來自定義模板內容,例如,一個假設的 <base-layout>
組件的模板以下:微信
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
複製代碼
在向具名插槽提供內容的時候,咱們能夠在一個父組件的 <template>
元素上使用 slot
特性:ide
<base-layout>
<template slot="header">
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template slot="footer">
<p>Here's some contact info</p>
</template>
</base-layout>
複製代碼
或者直接用在一個普通的元素上:函數
<base-layout>
<h1 slot="header">Here might be a page title</h1>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<p slot="footer">Here's some contact info</p>
</base-layout>
複製代碼
上述兩個示例渲染出來的 HTML 都將會是:學習
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
複製代碼
咱們可使用 v-slot
指令改寫上面的栗子:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
複製代碼
就是這麼簡單,插槽的名字如今經過 v-slot:slotName
這種形式來使用。
Tips: 沒有名字的
<slot>
隱含有一個"default"
名稱
例如,上面的默認插槽,若是你想顯示調用的話,能夠這樣:
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<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>
複製代碼
不管哪一種方式,上面的代碼都將輸出爲下面代碼:
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
複製代碼
請注意,
v-slot
只能添加到<template>
或自定義組件上,這點與棄用的 slot 屬性不一樣
在 2.6.0+ 中已棄用
有時候,咱們想在父組件中訪問子組件內部的一些可用數據。例如,假設有一個下面模板的 <current-user>
組件:
<span>
<slot>{{ user.lastName }}</slot>
</span>
複製代碼
咱們可能想用用戶的名字來替換掉插槽裏面的姓,因而咱們這樣寫:
<current-user>
{{ user.firstName }}
</current-user>
複製代碼
很不幸,上面這段代碼不能如你預期那樣工做,由於當前代碼的做用域環境是在父組件中,因此它訪問不了 <current-user>
內部的數據。
爲了解決這個, 咱們能夠在 <current-user>
內部的 <slot>
元素上動態綁定一個 user
對象屬性:
<span>
<!-- 完整 v-bind:user 下面是簡寫形式 -->
<slot :user="user">
{{ user.lastName }}
</slot>
</span>
複製代碼
綁定到 <slot>
元素上的屬性咱們稱之爲 slot props。如今,在父做用域中,咱們能夠經過 slot-scope
來訪問 user
數據了:
<current-user>
<template slot-scope="slotProp">
{{ slotProp.user.firstName }}
</template>
</current-user>
複製代碼
一樣的,咱們使用 v-slot
重構上面的代碼:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
複製代碼
或者直接做用在 <current-user>
上的寫法:
<!-- 省略默認插槽名字 -->
<current-user v-slot="slotProp">
{{ slotProp.user.firstName }}
</current-user>
<!-- 顯示調用默認插槽名字 -->
<current-user v-slot:default="slotProp">
{{ slotProp.user.firstName }}
</current-user>
複製代碼
在這個栗子中,咱們選擇
slotProp
做爲咱們的 slot props 名字,但你可使用你喜歡的任何名字。
在上述狀況下,當且僅當提供了默認插槽內容時,咱們可使用 v-slot
直接做用在組件上:
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
複製代碼
咱們能夠簡化上面的的默認插槽寫法:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
複製代碼
請注意了,默認插槽的縮寫語法不能與具名插槽混用:
<!-- 控制檯將報警告:-->
<!-- To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots. -->
<!-- 意思就是說,爲了不做用域模糊 -->
<!-- 當有其餘具名插槽時,默認插槽也應當使用 '<template>' 模板語法 -->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
<template v-slot:other="otherSlotProps">
slotProps is NOT available here
</template>
</current-user>
複製代碼
因而,上面的代碼,咱們改寫成:
<current-user>
<!-- 兩種寫法都可 -->
<!--<template v-slot="slotProps"> {{ slotProps.user.firstName }} </template>-->
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
複製代碼
在 Vue 代碼內部,咱們傳遞的 slotProps 其實就是函數的一個單一參數:
function (slotProps) {
// ... slot content ...
}
複製代碼
這也就意味着 v-slot
的值只要知足函數參數定義的 JavaScript 表達式的均可以接受。所以,在支持的環境(單文件或現代瀏覽器)中,你還可使用 ES2015 解構語法來提取特定的插值內容,例如:
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
複製代碼
代碼看起來更簡潔對吧。咱們還能夠重命名解構變量:
<current-user v-slot="{ user: person }">>
{{ person.firstName }}
</current-user>
複製代碼
這給了咱們不少自由操做的空間,你甚至能夠自定義回退內容,以便在未定義插值狀況下使用:
<current-user v-slot="{ user = { firstName: 'Guest' } }">>
{{ user.firstName }}
</current-user>
複製代碼
2.6.0+ 新增
動態指令參數 也適用於 v-slot
,容許咱們定義動態插槽名稱:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
複製代碼
2.6.0+ 新增
與 v-on
和 v-bind
相似,v-slot
也有一個簡寫,即便用 #
代替 v-slot
。例如, v-slot:header
簡寫成 #header
:
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>
複製代碼
和其餘指令同樣,只有在提供參數時才能使用簡寫形式,下面的寫法是無效的:
<!-- 將會觸發一個控制檯警告 -->
<current-user #="{ user }">
{{ user.firstName }}
</current-user>
複製代碼
也就是說,若是你想使用簡寫語法,則務必指定插值的名字:
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>
複製代碼
囉嗦了這麼多,但願看到的同窗或多或少有點收穫吧。不對的地方還請留言指正,不勝感激。俗話說,三人行則必有我師! 但願更多熱衷於 Vue 的小夥伴能聚在一塊兒交流技術!下面是我維護的一個Q羣,歡迎掃碼進羣哦,讓咱們一塊兒交流學習吧。也能夠加我我的微信:G911214255 ,備註 掘金
便可。