官网:https://cn.vuejs.org/guide/components/slots.html
在外部没有提供任何内容的情况下,可以为插槽指定默认内容。
<button type="submit">
<slot>
Submit
slot>
button>
当我们在父组件中使用
且没有提供任何插槽内容时:
<SubmitButton />
<SubmitButton>SaveSubmitButton>
<button type="submit">Submitbutton>
<button type="submit">Savebutton>
有时在一个组件中包含多个插槽出口是很有用的。举例来说,在一个
组件中,有如下模板:
<div class="container">
<header>
header>
<main>
main>
<footer>
footer>
div>
对于这种场景,
元素可以有一个特殊的 attribute name
,用来给各个插槽分配唯一的 ID
,以确定每一处要渲染的内容:
<div class="container">
<header>
<slot name="header">slot>
header>
<main>
<slot>slot>
main>
<footer>
<slot name="footer">slot>
footer>
div>
这类带 name
的插槽被称为具名插槽 (named slots)。没有提供 name
的
出口会隐式地命名为“default”
。
要为具名插槽传入内容,我们需要使用一个含 v-slot
指令的 元素,并将目标插槽的名字传给该指令:
<BaseLayout>
<template v-slot:header>
template>
<template #default>
<p>A paragraph for the main content.p>
<p>And another one.p>
template>
<p>A paragraph for the main content.p>
<p>And another one.p>
<template #footer>
<p>Here's some contact infop>
template>
BaseLayout>
v-slot
有对应的简写#
,因此可以简写为
。其意思就是“将这部分模板片段传入子组件的
header
插槽中”。
最终渲染出的 HTML 如下:
<div class="container">
<header>
<h1>Here might be a page titleh1>
header>
<main>
<p>A paragraph for the main content.p>
<p>And another one.p>
main>
<footer>
<p>Here's some contact infop>
footer>
div>
动态指令参数在 v-slot
上也是有效的,即可以定义下面这样的动态插槽名:
<base-layout>
<template v-slot:[dynamicSlotName]>
...
template>
<template #[dynamicSlotName]>
...
template>
base-layout>
插槽的内容想要同时使用父组件域内和子组件域内的数据,如下:
<div>
<slot :text="这是text" :count="1">slot>
div>
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
MyComponent>
<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>
<slot name="header" message="hello">slot>
注意:插槽上的
name
是一个 Vue 特别保留的attribute
,不会作为props
传递给插槽。因此最终headerProps
的结果是
{ message: 'hello' }
。
如果你同时使用了具名插槽与默认插槽,则需要为默认插槽使用显式的 标签。尝试直接为组件添加
v-slot
指令将导致编译错误。这是为了避免因默认插槽的 props 的作用域而困惑。举例:
<template>
<MyComponent v-slot="{ message }">
<p>{{ message }}p>
<template #footer>
<p>{{ message }}p>
template>
MyComponent>
template>
为默认插槽使用显式的 标签有助于更清晰地指出
message
属性在其他插槽中不可用:
<template>
<MyComponent>
<template #default="{ message }">
<p>{{ message }}p>
template>
<template #footer>
<p>Here's some contact infop>
template>
MyComponent>
template>
它会渲染一个列表,并同时会封装一些加载远端数据的逻辑、使用数据进行列表渲染、或者是像分页或无限滚动这样更进阶的功能。
<FancyList :api-url="url" :per-page="10">
<template #item="{ body, username, likes }">
<div class="item">
<p>{{ body }}p>
<p>by {{ username }} | {{ likes }} likesp>
div>
template>
FancyList>
在
之中,我们可以多次渲染
并每次都提供不同的数据 (注意我们这里使用了 v-bind
来传递插槽的 props
):
<ul>
<li v-for="item in items">
<slot name="item" v-bind="item">slot>
li>
ul>