1.插槽的作用:
当你在组件A中使用另一个组件B时,在组件标签下插入了一段html代码,在渲染的时候会直接被抛弃掉,为了让这段html代码成功渲染出来,可以在 组件B 中使用 插槽<slot></slot>,这样组件在渲染的时候 <slot></slot> 就会被替换成你写的那段html代码。(当然插槽内可以包含任何模版代码,包括html代码和其他组件)
// 组件a-show
<template>
<div class="test-slot">
// 组件b-slot
<b-slot></b-slot>
</div>
</template>
// 组件 b-slot
<template>
<div class="test-slot">
<h2>插槽slot</h2>
<slot>这里是插槽</slot>
</div>
</template>
当<b-slot></b-slot>中没有内容时,渲染时会将 <slot></slot> 中的内容被渲染出来,页面显示:
当<b-slot></b-slot>中有内容时,渲染时会将 <slot></slot> 中的内容会被<b-slot></b-slot>中的内容替换掉
// 组件a-show
<template>
<div class="test-slot">
// 组件b-slot
<b-slot>组件a-show</b-slot>
</div>
</template>
// 组件 b-slot
<template>
<div class="test-slot">
<h2>插槽slot</h2>
<slot>这里是插槽</slot>
</div>
</template>
此时页面显示为:
可以发现 <slot></slot> 中的内容这里是插槽 被 组件a-show 覆盖掉了
2.具名插槽
有时候我们需要将不同的内容放置到不同的位置时,就可以使用到 <slot> 元素的一个 attribute:name,来定义额外的插槽:
<div class="container">
<header>
<!-- 我们希望把页头放这里 -->
</header>
<main>
<!-- 我们希望把主要内容放这里 -->
</main>
<footer>
<!-- 我们希望把页脚放这里 -->
</footer>
</div>
一个不带 name 的 <slot> 出口会带有隐含的名字 "default"
向具名插槽提供内容时,可以在 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:
// 组件a-show
<template>
<div class="test-slot">
// 组件b-slot
<b-slot>
<template v-slot:footer>
<h3>这里是footer的内容</h3>
</template>
<template v-slot:header>
<h3>这里是header的内容</h3>
</template>
<template v-slot:default>
<h3>这里是main的内容</h3>
</template>
</b-slot>
</div>
</template>
// 组件 b-slot
<template>
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
可以看到通过 v-slot 的参数 来决定当前内容放到哪一个插槽中
任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容
注意:v-slot 只能添加在 <template> 上
3.作用域插槽
2.6.0开始, slot-scope 已被废弃使用
有一条规则:父级模块里的所有内容都是在父级作用域中编译的;子模块里的所有内容都是在自作用域中编译的
有时候我们需要在父级的插槽内容中访问子组件中的数据,这些数据是在父级渲染的,无法访问到子模块中的作用域。为了让在父级的插槽内容中可以访问子组件中的数据,可以将 userData 作为 <slot> 的一个属性绑定上去:<slot :userData ="userData "></slot> 绑定的属性被称为 插槽prop ,此时在父级作用域中,可以使用 带值的 v-slot 来定义我们提供的插槽prop的名字:
// 组件a-show
<template>
<div class="test-slot">
// 组件b-slot
<b-slot>
<template v-slot:sendValue="slotProps">{{ slotProps }}</template>
</b-slot>
</div>
</template>
// 组件 b-slot
<template>
<div class="test-slot">
<slot :dataList="dataList" name="sendValue"></slot>
</div>
</template>
可以看到此时可以在父级插槽内容中访问子作用域中的数据:
- 默认插槽的缩写语法
当插槽没有使用 name 属性时,被提供的内容只有默认插槽时,组件的标签才可以被当做插槽的模版来使用,这样就可以把 v-slot 直接用在组件上:<b-slot v-slot:default="slotProps"> {{ slotProps }} </b-slot>
更简单点:<b-slot v-slot="slotProps"> {{ slotProps }} </b-slot>
注意:默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
// 无效,会导致警告
<b-slot v-slot="slotProps">
<template v-slot:sendValue="otherSlotProps">{{ slotProps }}</template>
</b-slot>
- 解构插槽props
解构传入的具体插槽 prop:
<b-slot v-slot="{dataList}">
{{ dataList}}
</b-slot>
直接读出了 子作用域中 dataList 的value值,而使用 <b-slot v-slot="slotProps">{{ slotProps }}</b-slot> 读出的是一个对象值,如下所示:
slotProps = { dataList: "我是传值" }
prop重命名:将 user 重名名为 dataList
<b-slot v-slot="{dataList:list}">
{{ list}}
</b-slot>
4.具名插槽的缩写
2.6.0新增
把参数之前的所有内容 v-slot: 替换为字符 # ;例如 v-slot:header 可写成: #header
# 只有在 name属性有参数时才可使用,或使用: #defualt