# 插槽slot
# 插槽内容
- 自定义组件元素内容可以覆盖子组件内的slot元素,元素内容可以是另一个组件。
- 如果子组件没有slot传入的元素内容不会被使用
<navigation-link url="/profile">Your Profile</navigation-link>
<!-- 模板内容 -->
<a
:href="url"
class="nav-link"
>
<slot></slot>
</a>
# 编译作用域
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
<navigation-link url="/profile">
Clicking here will send you to: {{ url }}
<!--
这里的 `url` 会是 undefined,因为 "/profile" 是
_传递给_ <navigation-link> 的而不是
在 <navigation-link> 组件*内部*定义的。
-->
</navigation-link>
# slot默认替代值(后背内容)
<button type="submit">
<slot>Submit</slot>
</button>
<!-- 如果使用该模板,没传入元素内容,那么slot会渲染为Submit -->
<!-- 如果提供了内容就会使用提供的内容 -->
# 具名插槽
一个子组件内有多个slot插槽时,会通过name属性指定插槽名称,这种插槽就是具名插槽。
- 2.6.0+ 写法 v-slot:header
- 废弃的写法 slot="header"
// template 里面,没命名的slot元素,隐藏的名字为 "default"
Vue.component('page-layout', {
template: `
<div>
<header>
<slot name="header">header插槽默认内容</slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer">footer插槽默认内容</slot>
</footer>
</div>
`
})
使用该组件,用template元素包裹,v-slot:插槽名,向对应的具名插槽提供内容。注意 v-slot 只能添加在一个template元素上。
<page-layout>
<template v-slot:header>
<h1>Title</h1>
</template>
<p> 一个段落在main content</p>
<p>And another one.</p>
<template v-slot:footer>
<p>Here's some contact info</p>
</template>
</page-layout>
# 作用域插槽
- 2.6.0+ 写法 v-slot:header="slotProps"
- 废弃的写法 slot="header" slot-scope="slotProps"
<!-- user在父组件里渲染,无法访问user,需要要子组件的插槽把值传出来 -->
<current-user>
{{ user.firstName }}
</current-user>
<script>
Vue.component('current-user', {
template: `
<span>
<slot>{{ user.lastName }}</slot>
</span>
`
})
</script>
<!--
1.为了让user在父级的插槽内容中可用,可以将user作为slot元素的一个特性绑定上去
2.组件元素使用v-solt:default="slotProps"就可以访问值了。
-->
<current-user v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</current-user>
<script>
Vue.component('current-user', {
template: `
<span>
<slot v-bind:user="user">{{ user.lastName }}</slot>
</span>
`
// 具名插槽 <slot name="footer">footer插槽默认内容</slot>
})
</script>
# 仅有一个插槽时的简写
如果仅有一个插槽 v-slot:default可以简写为v-slot,但如果有两个或两个以上的插槽,就不能使用简写了。
<!-- 单个插槽可简写-->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
<!-- 多个插槽 -->
<current-user>
<template v-slot:default="slotProps"> <!-- <template v-slot:header> -->
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
# 解构插槽prop
插槽内部传出来的变量,赋值给组件元素时,可以使用结构赋值
<!--
template: `
<span>
<slot v-bind:user="user">{{ user.lastName }}</slot>
</span>
`
-->
<!-- 一般写法-->
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
<!-- 解构写法 -->
<current-user v-slot="{ user }">
{{ user.firstName }}
</current-user>
<!-- 解构写法,将user重命名为person -->
<current-user v-slot="{ user: person }">
{{ user.firstName }}
</current-user>
<!-- 解构写法,设置默认值,如果插槽prop的值为undefined -->
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{{ user.firstName }}
</current-user>
# 动态插槽名
动态指令参数也可以用在v-slot上,来定义动态的插槽名
<!-- 一般的动态指令参数: -->
<input v-bind:[attrname]="dosomething" v-model="name">
<!-- 动态指令参数-->
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
# 具名插槽的缩写(2.6.0+)
v-slot:可以简写为#,和其他指令一样,只有在有参数的时候才可用
<template v-slot:header>
<h1>Title</h1>
</template>
可以简写为:
<template #header>
<h1>Title</h1>
</template>
<!-- 不可用 -->
<current-user #="slotProps">
{{ slotProps.user.firstName }}
</current-user>
<!-- 如果想使用可以给一个默认的值 -->
<current-user #default="slotProps">
{{ slotProps.user.firstName }}
</current-user>