在Vue的官方文檔中,關於v-slot插槽的使用,介紹的不是非常清晰明確,插槽這個東西其實很好理解,當我們定義了一個Vue組件後,我們是不能在調用組件時在裏面再定義其它的dom結構的:
<submit-button>
<div>Save</div>
</submit-button>
上述這種結構是不合法的,如果 submit-button組件裏
沒有包含一個 <slot>
標籤,則該組件起始標籤和結束標籤之間的任何內容都不會被顯示,會被拋棄。那如果我們想在組件中再嵌入其它的dom結構該怎麼辦呢,這個時候就可以用到插槽這個功能了。在react同樣具備這個功能,只不過他不向Vue那樣封的這麼徹底,給你幾個明明白白的屬性供你去使用,而是更貼近原生:
<!-- HTML -->
<Range>
<Text>插槽</Text>
<Text>react native</Text>
</Range>
// JSX語法
export default class Range extends Component {
constructor(props) {
super(props)
}
render() {
return (
<View style={styles.body}>
{this.props.children}
</View>
)
}
在react中是通過this.props.children這個屬性來拿到組件中定義的dom結構,並在組件中定義位置去渲染。看到react的這個示例後,對你瞭解Vue的插槽應該能起到一定的幫助。
簡單的說,插槽就是讓你能夠在組件標籤中再定義其它的DOM結構。
插槽內容
插槽內可以包含任何模板代碼,包括 HTML或者其它組件:
<!-- 添加HTML內容 -->
<touch-bar>
<!-- 添加一個 Font Awesome 圖標 -->
<span class="fa fa-user"></span>
點擊這裏
</touch-bar>
<!-- 添加其它組件 -->
<touch-bar>
<!-- 添加一個按鈕的組件 -->
<touch-button name="user"></touch-button>
點擊這裏
</touch-bar>
編譯作用域
在Vue當中,父級模板裏的所有內容都是在父級作用域中編譯的;子模板裏的所有內容都是在子作用域中編譯的。
<navigation-link url="/profile">
Logged in as {{ user.name }}
</navigation-link>
在上面代碼中,該插槽跟模板的其它地方一樣可以訪問相同的實例屬性 (也就是相同的“作用域”)user.name,而不能訪問 <navigation-link>
的作用域。例如 url
是訪問不到的:
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
</navigation-link>
這裏的 `url` 會是 undefined,因爲 "/profile" 是傳遞給<navigation-link>組件的而不是在 <navigation-link> 組件標籤內部定義的。
插槽的默認內容
有時爲一個插槽設置具體的後備 (也就是默認的) 內容是很有用的,它只會在沒有提供內容的時候被渲染。例如在一個 <submit-button>
組件中,我們可能希望這個 <button>
內絕大多數情況下都渲染文本“Submit”。爲了將“Submit”作爲後備內容,我們可以將它放在 <slot>
標籤內:
<button type="submit">
<slot>Submit</slot>
</button>
現在當我在一個父級組件中使用 <submit-button>
並且不提供任何插槽內容時,後備內容“Submit”將會被渲染,但是如果我們提供內容,則這個提供的內容將會被渲染從而取代後備內容:
<!-- 不提供內容 -->
<submit-button></submit-button>
<!-- 提供內容 -->
<submit-button>
Save
</submit-button>
具名插槽
有時我們在一個組件需要多個插槽,每個插槽被用在組件的不同的位置,對於這樣的情況,<slot>
元素有一個特殊的特性:name,
這個特性可以用來定義額外的插槽的名稱,一個不帶 name
的 <slot>
會默認帶有隱含的屬性“default”:
<!-- 組件定義 -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
那麼我們該如何使用呢?在向具名插槽提供內容的時候,我們可以在一個 <template>
元素上使用 v-slot
指令,並以 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
只能添加在一個 <template>
上
作用域插槽
有時讓插槽內容能夠訪問子組件中才有的數據是很有用的,這就正好解決了上面所說的編譯作用域的問題。例如,設想一個帶有如下模板的 <current-user>
組件,我們想讓它的後備內容顯示用戶的名,以取代正常情況下用戶的姓,如下:
<!-- current-user組件定義 -->
<span>
<slot>{{ user.lastName }}</slot>
</span>
<!-- 使用current-user組件 -->
<current-user>
{{ user.firstName }}
</current-user>
上述代碼不會正常工作,因爲只有父級中 <current-user>
組件可以訪問到 user.firstName
,我們提供的內容是在父級渲染的,所以在<current-user>組件中定義的插槽拿不到user.lastName
。
爲了讓 user
在父級的插槽內容中可用,我們可以將 user
作爲 <slot>
元素的一個特性綁定上去,綁定在 <slot>
元素上的特性被稱爲插槽 prop。
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
在父級作用域中,我們還可以給<current-user>中的
v-slot
給定一個值來定義插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
以上就是關於Vue插槽的講述!