<app>
<menu-main></menu-main>
<menu-sub></menu-sub>
<div>
<app-footer></app-footer>
</div>
</app>
以
为例,在
中混合了父组件的内容和子组件的模板时,就会用到slot,这个过程叫做内容分发。
使用slot的组件有两个特点:
1.它创建时不知道某个部分需要挂载什么,这部分内容需要父组件调用时决定。
2.组件可能有它自己的模板。
//父组件
<child-component v-show="show">
{
{
messge}}
</child-component>
//子组件child-component
<template>
<h1>{
{
title}}</h1>
<div>
<slot></slot>
</div>
</template>
在上述代码中,父组件引用child-component子组件,{ {message}}就是一个插槽slot,它绑定的时父组件的数据,而不是子组件的数据。所以它是在父组件的作用域中编译。v-show绑定的参数show也是父组件的数据。
{ {title}}是子组件的数据,所以它是在子组件的作用域中编译。
slot分成三类: 匿名插槽、具名插槽、作用域插槽
有时候我们在组件中希望使用多个插槽,为了能识别父组件传入的插值数据在正确的位置,我们可以给slot加上name,以便区分。
例如
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
</main>
<footer>
<!-- 我们希望把页脚放这里 -->
</footer>
</div>
它希望有三处插槽。我们可以这么定义
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
//或者
<slot name="default"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
这些带有name的插槽,我们就叫做具名插槽。没有带有name的(
)我们称为匿名插槽。
父元素调用:
<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>
我们在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称,现在 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 中的内容都会被视为默认插槽的内容。如果你想更清晰一点,可以给默认的插槽加上 v-slot=“default”。注意 v-slot 只能添加在一个
上。
上的插槽名称也可以是动态的。如:dynamicSlotName的值可以改变。
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
</base-layout>
具名插槽的缩写: v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header。匿名插槽缩写需要带上default,如#default="{user}",否则#=“{user}”无效。
作用域插槽是一种特殊的slot,通常情况下,插槽访问的数据都来自于父组件,但是有时候我们需要插槽访问子组件的数据,为了让 子组件数据 在父级的插槽内容中可用,我们可以将数据 作为 元素的一个特性绑定上去。
例如:
//子组件
<span>
<slot v-bind:user="user">
{
{
user.lastName }}
</slot>
</span>
//父组件
<current-user>
<template v-slot:default="slotProps">
{
{
slotProps.user.firstName }}
</template>
</current-user>
绑定在 元素上的特性被称为插槽 prop( v-bind:user=“user”)。现在在父级作用域中,我们可以给 v-slot 带一个值来定义我们提供的插槽 prop 的名字。v-slot:default="xxx"名字可以任意。当存在具名插槽时,匿名插槽.default不能去掉,否则会造成作用域不明确。
我们可以用解构的方式接受子组件传递过来的参数。例如上面例子,
//父组件
<current-user>
//
<template v-slot:default="{ user }">
{
{
slotProps.user.firstName }}
</template>
</current-user>
子组件传递属性值为user,父组件接受时结果会包裹在一个对象中,所以在支持的环境下 (单文件组件或现代浏览器),我们可以直接解构出来。
prop也可以重命名,如代码,我们将接受的user重命名为person。
<current-user v-slot="{ user: person }">
{
{
person.firstName }}
</current-user>
prop也可以设置默认值,当prop接受的数据位undifined时取默认值。
<current-user v-slot="{ user = { firstName: 'Guest' } }">
{
{
user.firstName }}
</current-user>
user设置默认值 { firstName: ‘Guest’ }