Vue
【vue】插槽
12-24 11:04插槽是什么
插槽(slot)是 Vue 为组件的封装者提供的能力,允许开发者在封装组件时,把“不确定的、希望由用户指定的部分”定义为插槽。
体验插槽基本用法
定义插槽:在封装组件时,可以通过 <slot> 元素定义插槽,从而为用户预留内容占位符,通过案例说明,比如:在 SlotMain 中使用 SlotA 的插槽。
1、在 SlotA.vue 中定义插槽:
<template>
<p>SlotA组件第一个标签</p>
<!-- 通过 slot 标签,为用户预留内容占位符(插槽),组件使用者可在此插入自定义内容 -->
<slot></slot>
<p>SlotA组件最后一个标签</p>
</template>
<script>
export default {
name: 'SlotA',
}
</script>
2、在 SlotMain.vue 中使用插槽:引入 SlotA 组件,使用其中的插槽
<template>
<!-- 在使用 SlotOne 组件时,为插槽指定具体的内容 -->
<SlotA>
<p>插槽数据</p>
</SlotA>
</template>
<script>
import SlotA from 'SlotA.vue'
export default {
name: 'SlotMain',
components: {
SlotA
}
}
</script>
没有预留插槽的内容会被丢弃
如果在封装组件时,没有预留任何 <slot> 插槽,则用户提供的任何自定义内容都会被丢弃。
<template>
<p>SlotA 组件第一个标签</p>
<!-- 封装组件时,没有预留任何插槽 -->
<p>SlotA 组件最后一个标签</p>
</template>
使用插槽:
<template>
<SlotA>
<!-- 自定义的内容会被丢弃-->
<p>插槽数据</p>
</SlotA>
</template>
插槽后备内容
封装组件时,可以为预留的 <slot> 插槽提供后备内容(默认内容)。如果组件的使用者没有为插槽提供任何内容,则后备内容会生效。

具名插槽
如果在封装组件时需要预留多个插槽节点,则需要为每个 <slot> 插槽指定具体的 name 名称。这种带有具体名称的插槽叫做“具名插槽”。

为具名插槽提供内容
引入含有具名插槽的组件后,向具名插槽提供内容时,可以在一个 <template> 元素上使用 v-slot 命令,并以 v-slot 的参数的形式提供其名称。
使用具名插槽的注意事项:
1、起了 name 名称的插槽,一定要使用 template 标签来包裹,并使用 v-slot 指明插槽名称;
2、v-slot 只能在 template 标签上,放在 div、h1 等 html 标签上不生效;
3、只有默认插槽在使用时可以省略外层的 template;
4、没有指定 name 时,默认都放到 default 插槽中。
补充:template 是 vue 提供的标签,它不会被渲染成任何实质性元素,只提供包裹作用。

具名插槽的简写形式
类似 v-on 和 v-bind 的简写“@”和“:”,v-slot 也有缩写,即把“v-slot:”命令替换为“#”,如下:
<template v-slot:header></template>
<!-- v-slot:header 可以被简写为 #header -->
<template #header></template>
具体案例

作用域插槽
在封装组件的过程中,可以为预留的 <slot> 插槽通过 v-bind 绑定 props 数据,这种带有 props 数据的 <slot> 叫做“作用域插槽”。
通俗理解,作用域插槽可以动态绑定数据,组件中 data 节点和 props 节点中的数据都可以绑定到插槽上。
在组件中定义作用域插槽,如下:

外界在使用当前组件时,除了对这个插槽进行内容填充,还可以接收插槽对外提供的数据
外界怎么接收?在v-slot:插槽名称后面用等号接收插槽对外提供的数据(接收时参数名可随意,scope比较常见)比如:
<template v-slot:default="scope"> ... </template>
<!-- 简写具名插槽 -->
<template #default="scope"> ... </template>
无需事先定义变量,接收到即可直接使用
<template v-slot:default="scope">
{{ scope }}
</template>
比如:

外界接收到的变量是一个大对象(Json),里面包含插槽绑定的所有数据,比如上面案例中插槽绑定的数据,接收到的结果如下:

获取其中某个值:
<template #default="scope">
<p>{{ scope.info.name }}</p>
<template>
解构作用域插槽的prop
作用域插槽对外提供的是一个对象数据,外面使用时,接收到的也是一个对象,里面包含了插槽通过属性绑定方式对外提供的所有数据,访问某个数据时,需要通过接收到的对象依次往下访问。
既然接收到的是一个对象,直接使用对象的结构赋值也可以,即:需要对外传递的哪个属性,直接把对应的名字放在花括号中即可,比如:
<template #default="{ info, message }"> ... <template>

作用域插槽的实际应用
比如要封装一个列表数据,此时有个表示状态的字段,值是布尔,但组件中无法确定怎样展示,需要交给组件使用者确定
抛出问题的代码:


解决方法:在封装组件的过程中,通过作用域插槽把表格每一行数据传递给组件使用者。

使用组件时,接收作用域插槽对外提供的数据,自定义单元格的渲染方式。

得到如下效果:
