插槽内容
ComponentA组件
<template>
<div>
<a
v-bind:href="url"
class="nav-link"
>
<slot></slot>
</a>
</div>
</template>
引用
<component-a>
Your Profile
</component-a>
渲染成,slot就会被<component-a>
标签中的内容所替代
<template>
<div>
<a
v-bind:href="url"
class="nav-link"
>
Your Profile
</a>
</div>
</template>
编译作用域
<navigation-link url="/profile">
{{ user.name }}
</navigation-link>
该插槽跟模板的其它地方一样可以访问相同的实例属性 (也就是相同的“作用域”),而不能访问 <navigation-link>
的作用域,如url
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
<!--
这里的 `url` 会是 undefined,因为 "/profile" 是
_传递给_ <navigation-link> 的而不是
在 <navigation-link> 组件*内部*定义的。
-->
</navigation-link>
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的
。
后备内容
如confirm-button
组件
<button type="submit">
<slot>确定</slot>
</button>
当使用组件,并且不提供任何插槽内容时
<confirm-button><confirm-button>
插槽内容将会使用后备内容
<button type="submit">
确定
</button>
但是如果提供内容则使用提供的内容
<confirm-button>保存<confirm-button>
<button type="submit">
保存
</button>
具名插槽-------------------------------------------重点
<base-layout>
组件
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
</main>
<footer>
<!-- 我们希望把页脚放这里 -->
</footer>
</div>
此时需要用到slot的name属性,可以定义多个插槽
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
一个不带 name 的 出口会带有隐含的名字“default”。
<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>
具体使用的时候,需要在一个 <template>
元素上使用 v-slot 指令,并根据name值对应上参数
如果你希望更明确一些,仍然可以在一个 <template>
中包裹默认插槽的内容
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<template v-slot:default>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</template>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
渲染成
<div class="container">
<header>
<h1>Here might be a page title</h1>
</header>
<main>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
</main>
<footer>
<p>Here's some contact info</p>
</footer>
</div>
注意 v-slot 只能添加在 <template> 上 (只有一种例外情况),这一点和已经废弃的 slot 特性不同。
作用域插槽
有时让插槽内容能够访问子组件中才有的数据是很有用的。例如,设想一个带有如下模板的 <current-user>
组件
<span>
<slot>{{ user.lastName }}</slot>
</span>
我们想让它的后备内容显示用户的名,以取代正常情况下用户的姓,如下
<current-user>
{{ user.firstName }}
</current-user>
然而上述代码不会正常工作,因为只有 <current-user>
组件可以访问到 user 而我们提供的内容是在父级渲染的。
为了让 user 在父级的插槽内容中可用,我们可以将 user 作为 <slot>
元素的一个特性绑定上去:
<span>
<slot :user="user">
{{ user.lastName }}
</slot>
</span>
绑定在 <slot>
元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
在这个例子中,我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字
独占默认插槽的缩写语法
当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。这样我们就可以把 v-slot 直接用在组件上:
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
这种写法还可以更简单。就像假定未指明的内容对应默认插槽一样,不带参数的 v-slot 被假定对应默认插槽:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template>
的语法
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
具名插槽的缩写
即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:
<base-layout>
<template #header>
<h1>Here might be a page title</h1>
</template>
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #footer>
<p>Here's some contact info</p>
</template>
</base-layout>