默认插槽
在子组件中通过<slot></slot>标签包裹的内容就是默认的插槽内容,在父组件中使子组件时,就会显示默认的插槽内容,如果父组件的模板中写入了内容,就会替换默认的内容,这是默认插槽的基本用法
具名插槽
有时候,我们需要多个插槽,分别展示不同的内
<div class="container">
<header>
头部内容
</header>
<main>
主要内容
</main>
<footer>
底部内容
</footer>
</div>
这个时候就要用到具名插槽了,如果slot没有命名,默认的名字就是default
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
在子组件定义slot的用法,新旧版本都是一样的,不同的就是在父组件中使用时,稍有不同
<base-layout>
<template v-slot:header>header内容</tempalte>
<template v-slot:default>main内容</template>
<template v-slot:footer>footer内容</template>
</base-layout>
v-slot:header后面的就是在子组件中定义的slot名字
注意:v-slot只能加在template标签上(只有一种例外),这一点也和之前的用法不通
作用域插槽
首先,我们需要了解编译作用域,在父组件中使用子组件时,在子组件包裹的模板里面只能使用父组件的数据,不能直接使用子组件的数据。
<navigation-link url="/profile">
Logged in as {{ user.name }}
这里只能使用父组件中的user数据,不能使用子组件中的数据url
</navigation-link>
父级模板里的所有内容都是在父级作用域中编译的,子模板里的所有内容都是 在子作用域中编译的
有时需要在插槽内容中访问子组件中的数据,我们可以将子组件中的数据绑定到slot便签上去,在父组件中可以通过v-slot:default="slotProps"访问到子组件中的数据
//child.vue
<div>
<slot :user="user>{{user.name}</slot>
</div>
//parent.vue
<Child v-slot:default="slotProps">
<template v-slot:default="slotProps">{{slotProps.user.name}}</template>
</Child>
这里slotProps就是子组件中插槽传递的prop的自定义名称,在父组件中就可以使用slotProps.user.name访问子组件的数据了。当前,使用解构会更简单。
<Child v-slot:default="slotProps">
<template v-slot:default="{user}">{{user.name}}</template>
</Child>
当子组件中只有一个默认插槽时(没有其他具名插槽),才可以在组件名上直接使用v-slot:default="slotProps"
<Child v-slot:default="slotProps">{{slotProps.user.name}}</Child>
这种写法还可以简化,不带参数的v-slot对应的就是默认插槽
<Child v-slot="{user}">{{user.name}}</Child>
但是需要注意的是,如果子组件有多个插槽,请始终为所有插槽使用完整的基于template的语法
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
<template v-slot:other="otherSlotProps">
...
</template>
</current-user>
v-slot的缩写
跟v-on和一样,v-slot也有缩写,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>
简写的作用域插槽
<current-user #default="{ user }">
{{ user.firstName }}
</current-user>