插槽
該頁面假設你已經閱讀過了組件基礎。如果你還對組件不太了解,推薦你先閱讀它。
插槽內容
Vue 實現了一套內容分發的 API,這套 API 基于當前的?Web Components 規范草案,將?<slot>
?元素作為承載分發內容的出口。
它允許你像這樣合成組件:
<navigation-link url="/profile"> |
然后你在?<navigation-link>
?的模板中可能會寫為:
<a |
當組件渲染的時候,這個?<slot>
?元素將會被替換為“Your Profile”。插槽內可以包含任何模板代碼,包括 HTML:
<navigation-link url="/profile"> |
甚至其它的組件:
<navigation-link url="/profile"> |
如果?<navigation-link>
?沒有包含一個?<slot>
?元素,則任何傳入它的內容都會被拋棄。
具名插槽
有些時候我們需要多個插槽。例如,一個假設的?<base-layout>
?組件多模板如下:
<div class="container"> |
對于這樣的情況,<slot>
?元素有一個特殊的特性:name
。這個特性可以用來定義額外的插槽:
<div class="container"> |
在向具名插槽提供內容的時候,我們可以在一個父組件的?<template>
?元素上使用?slot
特性:
<base-layout> |
另一種?slot
?特性的用法是直接用在一個普通的元素上:
<base-layout> |
我們還是可以保留一個未命名插槽,這個插槽是默認插槽,也就是說它會作為所有未匹配到插槽的內容的統一出口。上述兩個示例渲染出來的 HTML 都將會是:
<div class="container"> |
默認插槽的內容
有的時候為插槽提供默認的內容是很有用的。例如,一個?<submit-button>
?組件可能希望這個按鈕的默認內容是“Submit”,但是同時允許用戶覆寫為“Save”、“Upload”或別的內容。
你可以在?<slot>
?標簽內部指定默認的內容來做到這一點。
<button type="submit"> |
如果父組件為這個插槽提供了內容,則默認的內容會被替換掉。
編譯作用域
當你想在插槽內使用數據時,例如:
<navigation-link url="/profile"> |
該插槽可以訪問跟這個模板的其它地方相同的實例屬性 (也就是說“作用域”是相同的)。但這個插槽不能訪問?<navigation-link>
?的作用域。例如嘗試訪問?url
?是不會工作的。牢記一條準則:
父組件模板的所有東西都會在父級作用域內編譯;子組件模板的所有東西都會在子級作用域內編譯。
作用域插槽
2.1.0+ 新增
有的時候你希望提供的組件帶有一個可從子組件獲取數據的可復用的插槽。例如一個簡單的?<todo-list>
?組件的模板可能包含了如下代碼:
<ul> |
但是在我們應用的某些部分,我們希望每個獨立的待辦項渲染出和?todo.text
?不太一樣的東西。這也是作用域插槽的用武之地。
為了讓這個特性成為可能,你需要做的全部事情就是將待辦項內容包裹在一個?<slot>
?元素上,然后將所有和其上下文相關的數據傳遞給這個插槽:在這個例子中,這個數據是?todo
?對象:
<ul> |
現在當我們使用?<todo-list>
?組件的時候,我們可以選擇為待辦項定義一個不一樣的?<template>
?作為替代方案,并且可以通過?slot-scope
?特性從子組件獲取數據:
<todo-list v-bind:todos="todos"> |
在 2.5.0+,
slot-scope
?不再限制在?<template>
?元素上使用,而可以用在插槽內的任何元素或組件上。
解構?slot-scope
如果一個 JavaScript 表達式在一個函數定義的參數位置有效,那么這個表達式實際上就可以被?slot-scope
?接受。也就是說你可以在支持的環境下 (單文件組件或現代瀏覽器),在這些表達式中使用?ES2015 解構語法。例如:
<todo-list v-bind:todos="todos"> |
這會使作用域插槽變得更干凈一些。