插槽内容与出口
FancyButton.vue:
<button class="fancy-btn">
<slot></slot> <!-- 插槽出口 -->
</button>
父页面使用:
<FancyButton>
Click me! <!-- 插槽内容 -->
</FancyButton>
最终渲染出的 DOM 是这样:
<button class="fancy-btn">Click me!</button>
插槽内容可以是任意合法的模板内容,不局限于文本。
如父页面可以使用:
<FancyButton>
<span style="color:red">Click me!</span>
<AwesomeIcon name="plus" />
</FancyButton>
渲染作用域
插槽内容无法访问子组件的数据。
父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。
默认内容
SubmitButton.vue:
<button type="submit">
<slot>
Submit <!-- 默认内容 -->
</slot>
</button>
父组件:
<SubmitButton />
或者:
<SubmitButton>Save</SubmitButton>
此时 , Save 会取代Submit
具名插槽
BaseLayout.vue:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
父组件:
<BaseLayout>
<template v-slot:header>
<!-- header 插槽的内容放这里 -->
</template>
</BaseLayout>
其中<template v-slot:header>可以简写为 <template #header>
完整的使用:
<BaseLayout>
<template #header>
Here might be a page title
</template>
<template #default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template #footer>
<p>Here's some contact info</p>
</template>
</BaseLayout>
作用域插槽
子组件MyComponent.vue:
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>
父组件使用:
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>
也可以在 v-slot 中使用解构:
<MyComponent v-slot="{ text, count }">
{{ text }} {{ count }}
</MyComponent>
具名作用域插槽
父组件使用:
<MyComponent>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #default="defaultProps">
{{ defaultProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</MyComponent>
高级列表组件示例
子组件:FancyList.vue
<ul>
<li v-for="item in items">
<slot name="item" v-bind="item"></slot>
</li>
</ul>
父组件使用:
<FancyList :api-url="url" :per-page="10">
<template #item="{ body, username, likes }">
<div class="item">
<p>{{ body }}</p>
<p>by {{ username }} | {{ likes }} likes</p>
</div>
</template>
</FancyList>