1.什麼是slot
<app>
<menu-main></menu-main>
<menu-sub></menu-sub>
<div>
<app-footer></app-footer>
</div>
</app>
以<app>
爲例,在<app>
中混合了父組件的內容和子組件的模板時,就會用到slot,這個過程叫做內容分發。
使用slot的組件有兩個特點:
1.它創建時不知道某個部分需要掛載什麼,這部分內容需要父組件調用時決定。
2.組件可能有它自己的模板。
編譯作用域
//父組件
<child-component v-show="show">
{{messge}}
</child-component>
//子組件child-component
<template>
<h1>{{title}}</h1>
<div>
<slot></slot>
</div>
</template>
在上述代碼中,父組件引用child-component子組件,{{message}}就是一個插槽slot,它綁定的時父組件的數據,而不是子組件的數據。所以它是在父組件的作用域中編譯。v-show綁定的參數show也是父組件的數據。
{{title}}是子組件的數據,所以它是在子組件的作用域中編譯。
slot用法
slot分成三類: 匿名插槽、具名插槽、作用域插槽
匿名插槽與具名插槽
有時候我們在組件中希望使用多個插槽,爲了能識別父組件傳入的插值數據在正確的位置,我們可以給slot加上name,以便區分。
例如<base-layout>組件
<div class="container">
<header>
<!-- 我們希望把頁頭放這裏 -->
</header>
<main>
<!-- 我們希望把主要內容放這裏 -->
</main>
<footer>
<!-- 我們希望把頁腳放這裏 -->
</footer>
</div>
它希望有三處插槽。我們可以這麼定義
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
//或者
<slot name="default"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
這些帶有name的插槽,我們就叫做具名插槽。沒有帶有name的(<slot></slot>
)我們稱爲匿名插槽。
父元素調用:
<base-layout>
// 會被渲染到<slot name="header"></slot>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
// 會被渲染到<slot></slot>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
// 會被渲染到<slot name="footer"></slot>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
我們在一個 元素上使用 v-slot 指令,並以 v-slot 的參數的形式提供其名稱,現在 <template>
元素中的所有內容都將會被傳入相應的插槽。任何沒有被包裹在帶有 v-slot 的 中的內容都會被視爲默認插槽的內容。如果你想更清晰一點,可以給默認的插槽加上 v-slot=“default”。注意 v-slot 只能添加在一個 <template>
上。
<template>
上的插槽名稱也可以是動態的。如:dynamicSlotName的值可以改變。
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
具名插槽的縮寫: v-slot 也有縮寫,即把參數之前的所有內容 (v-slot:) 替換爲字符 #。例如 v-slot:header 可以被重寫爲 #header。匿名插槽縮寫需要帶上default,如#default="{user}",否則#=“{user}”無效。
作用域插槽
作用域插槽是一種特殊的slot,通常情況下,插槽訪問的數據都來自於父組件,但是有時候我們需要插槽訪問子組件的數據,爲了讓 子組件數據 在父級的插槽內容中可用,我們可以將數據 作爲 元素的一個特性綁定上去。
例如:
//子組件
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
//父組件
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
綁定在 元素上的特性被稱爲插槽 prop( v-bind:user=“user”)。現在在父級作用域中,我們可以給 v-slot 帶一個值來定義我們提供的插槽 prop 的名字。v-slot:default="xxx"名字可以任意。當存在具名插槽時,匿名插槽.default不能去掉,否則會造成作用域不明確。
解構插槽 Prop
我們可以用解構的方式接受子組件傳遞過來的參數。例如上面例子,
//父組件
<current-user>
//<template v-slot:default="slotProps">
<template v-slot:default="{ user }">
{{ slotProps.user.firstName }}
</template>
</current-user>
子組件傳遞屬性值爲user,父組件接受時結果會包裹在一個對象中,所以在支持的環境下 (單文件組件或現代瀏覽器),我們可以直接解構出來。
prop也可以重命名,如代碼,我們將接受的user重命名爲person。
<current-user v-slot="{ user: person }">
{{ person.firstName }}
</current-user>
prop也可以設置默認值,當prop接受的數據位undifined時取默認值。
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>
user設置默認值 { firstName: ‘Guest’ }