Vue 中 slot 是什么?作用?分类?如何实现?

news/2024/12/29 7:10:59/

结论先行:

slot 插槽,是子组件提供给父组件使用的一个占位符,父组件可以在这个占位符中填充任何模板代码。主要作用就是更好的拓展和定制化组件,例如弹窗组件、表格组件等。分为默认插槽、具名插槽和作用域插槽。

其中前两个都是渲染在父级,本质上就是替换,父组件渲染完毕之后替换对应的 slot;区别在于具名插槽就是给插槽取了名字;

而作用域插槽在组件内部渲染。本质上会把父组件的内容渲染成函数,子组件调用函数,并且将数据传递给它。当需要将子组件的数据交给父组件展示,此时就可以使用作用域插槽。给数据一个新的作用域,因此叫做作用域插槽。 

应用场景:自定义的表格组件,允许用户传入自定义的结构 + 数据(从插槽中回传的)

1、什么是 slot ? 

① 官方文档 

官方文档 Vue2:插槽 — Vue.js

官方文档 Vue3:插槽 Slots | Vue.js 

② 概念 

slot(插槽)是一种用于分发内容的机制,一种用于在组件中传递内容的机制

也就是说在组件模板中利用 slot 进行占位,然后在使用组件时,传入的组件内容也就是 HTML 片段,会分发的对应的 slot 中。 

它允许你在组件的模板中定义带有特殊标记的区域,然后在使用该组件时填充这些区域。

通过 <slot></slot> 标签来定义一个插槽。这个插槽可以有默认内容,也可以是没有任何内容的。当使用该组件时,可以将内容插入到插槽中。

插槽可以有默认值,直接在 slot 里设置。

简单理解就是子组件中留下个“坑”,父组件可以使用指定内容来补“坑”。以下是一个简单的示例,展示了如何在 Vue 组件中使用插槽:

<!-- 父组件 -->
<template><div><h1>父组件</h1><ChildComponent><p>这是插入到子组件中的内容</p></ChildComponent></div>
</template><!-- 子组件 -->
<template><div><h2>子组件</h2><!-- 这里是插槽 --><slot></slot></div>
</template>

在上面的示例中,父组件中的 <ChildComponent> 标签包含了一个 <p> 标签,作为插入到子组件中的内容。子组件中的 <slot></slot> 标签表示一个插槽,它将会被父组件中的内容所填充。

③ 内容定义方式 

在 Vue2.6.0 之后,使用 v-slot 或者语法糖 #插槽名 定义;在这之前使用 slot="插槽名" 定义。 

跟 v-on 和 v-bind 一样,v-slot 也有缩写,也就是把参数之前的所有内容 (v-slot:) 替换为字符 #

下面是三种 默认插槽 的内容定义方式,并且最后一个默认插槽的内容会覆盖掉上一个插槽内容 

使用 template 包裹内容,同时使用 v-slot 绑定一个名称。  

v-slot 一般跟 template 标签使用 (template 是 html5 新出的标签内容模板元素,不会渲染到页面上, 一般被 vue 解析为内部标签)

<child><template><span style="color: red">这里是默认插槽内容1,字体为红色</span></template><template v-slot:default><span style="color: yellow">这里是默认插槽内容2,字体为h黄色</span></template><template #default><span style="color: blue">这里是默认插槽内容3,字体为蓝色</span></template>
</child>
④ 独占默认插槽的缩写  

v-slot:default="slotProps" 可以简写为 v-slot="slotProps"

如果我们的插槽只有默认插槽时,组件的标签可以被当做插槽的模板来使用。

也就是可以将 v-slot 直接用在组件上

2、插槽的作用 ? 

通过使用插槽,我们可以实现更加灵活和可复用的组件,增强组件的可复用性。

当一个组件需要接收外部传入的内容时,可以使用插槽来实现这个功能。

同时,插槽还可以指定默认内容,当没有提供具体内容时将显示默认内容。 

通过插槽可以让用户更好的对组件进行拓展和定制化,可以通过具名插槽指定渲染的位置。

常用的组件例如:弹窗组件、布局组件、表格组件……

3、插槽的分类 

① 默认插槽

不指定插槽 name 属性。也就是插槽的内容出口(不写名字出口会带有隐含的名字“default”)

  • 默认插槽是指在父组件中没有提供具名插槽名称的情况下使用的插槽。父组件中未匹配到具名插槽的内容会被放置在默认插槽中。
  • 在 Vue 2 中,默认插槽是不带任何属性的 <slot> 元素。
  • 在 Vue 3 中,默认插槽使用 v-slot 指令来定义。

<slot name="default"></slot>   或者  <slot></slot>

<!-- 父组件 -->
<template><div><h1>父组件</h1><ChildComponent><p>这是插入到子组件中的内容</p></ChildComponent></div>
</template><!-- 子组件 -->
<template><div><h2>子组件</h2><!-- 这里是插槽 --><slot></slot></div>
</template>
② 具名插槽

渲染在父级(父组件渲染好了,子组件根据 slot 对应的名字来替换就可以);

本质上就是替换,普通插槽就是在父组件渲染完毕之后,使用子组件替换掉父组件的占位符 slot;

定义: <slot name="xxx">

使用:

  • <template #xxx></template>;
  • <template v-slot:xxx></template>
  • 具名插槽允许子组件将内容分发到父组件中指定名称的插槽上。
  • 在 Vue 2 中,可以通过给 <slot> 元素添加 name 属性来创建具名插槽,然后在父组件中使用 <template v-slot:slotName> 或者 <slot name="slotName"> 来引用具名插槽。
  • 在 Vue 3 中,具名插槽被称为命名插槽,可以使用新的 v-slot 指令来定义。
<!-- 子组件 -->
<div><!-- 具名插槽:指定了name属性, 内容出口 --><slot name="name-1"></slot>
</div><!-- 父组件 -->
<child>
<template v-slot:name-1="slotProps"><span style="color: red">{{ slotProps.user.firstName }}这里是具名插槽内容1,字体为红色</span>
</template><template #name-1="{ user }"><span style="color: yellow">{{ user.firstName }}这里是具名插槽内容2,字体为黄色</span>
</template>
</child>

下面是两种 具名插槽 的内容定义方式,并且最后一个插槽的内容会覆盖掉上一个插槽内容。

注意:默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确

③ 作用域插槽

作用域插槽:把组件内的值取出来自定义显示内容。 

作用域插槽在组件内部渲染。本质上会把父组件的内容渲染成函数,子组件调用函数,并且将数据传递给它。函数的返回值就会替换掉这个占位符。

  • 作用域插槽允许子组件将数据传递到父组件中的插槽内容中,使得父组件可以使用子组件中的数据进行渲染。
  • 在 Vue2 中,作用域插槽通过 <slot> 元素的 name 属性以及 <template slot-scope="props"> 来实现。
  • 在 Vue 3 中,作用域插槽的语法发生了变化,使用 v-slot 指令和新的 # 符号来指定插槽的作用域

组件内变量绑定在 slot 上,然后使用组件 v-slot:插槽名字="变量" ,变量上就会绑定 slot 传递的属性和值,插槽可以自定义显示内容;

运用场景:自定义的表格组件,允许用户传入:自定义的结构 + 数据(从插槽中回传的)

scope:是我指定的作用域这个作用域是插槽的作用域。可以获取插槽上除 name 属性外的其他自定义属性,来获取到插槽上的数据

在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽

<!-- 子组件 -->
<div><slot name="name-1" slotMessage="信息1" slotMessage2="信息2"></slot>
</div><!-- 父组件 -->
<child><template #name-1="scope"><!-- 下面这些值将会展示到插槽出口位置 --><span>{{ scope }}</span><br><span>{{ scope.slotMessage1 }}</span><br><span>{{ scope.slotMessage2 }}</span><br></template>
</child>

当需要将子组件的数据交给父组件展示,此时就可以使用作用域插槽。在子组件中,在 slot 中使用v-bind 绑定需要传递的数据 

<slot :testProps="list">插槽后备内容</slot> //在父组件中的子组件名中使用v-slot="属性名"的方式接受 
<Child> <template v-slot="testProps"> <p v-for="item in testProps" :key="item.id"> {{ item.name }} </p> </template>
</Child>

4、动态插槽名 

 目前我们使用的插槽名称都是固定的,比如 v-slot:left、v-slot:center 等等;

我们可以通过 v-slot:[dynamicSlotName] 方式动态绑定一个名称;

4、Vue2 和 Vue3 的区别

① 都能使用 v-slot:name 或者其缩写 #name 的方式来定义具名插槽;

② 如果在父组件中传入多个插槽内容,那 Vue2 总是会展示最后一个插槽的内容,Vue3 会展示第一个插槽内容。

③ 作用域插槽,Vue2.x 的机制导致作用域插槽变了,父组件会重新渲染。而 Vue3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能

5、总结

① v-slot 属性只能在 <template> 上使用,但在只有默认插槽时可以在组件标签上使用;

② 默认插槽名为 default,可以省略 default 直接写v-slot;

③ 缩写为 时不能不写参数,写成 #default

④ 可以通过解构获取 v-slot={user},还可以重命名 v-slot="{user: newName}" 和定义默认值 v-slot="{user = '默认值'}"

在Vue中有渲染作用域的概念:

  • 父级模板里的所有内容都是在父级作用域中编译的
  • 子模板里的所有内容都是在子作用域中编译的

  • 组件 ChildCpn 中,可以拿到自己作用域中的 title 内容;
  • 但是在 App 中,是访问不了 ChildCpn 中的内容的,因为它们是跨作用域的访问;


http://www.ppmy.cn/news/1221727.html

相关文章

基于架构软件设计方法及应用

随着国内外化工行业的繁荣与发展&#xff0c;从2018年开始&#xff0c;某能源集团下属的化工部&#xff0c;连续投资建设了MES&#xff08;生产制造&#xff09;系统、设备管理系统、安全管控系统、能源管理系统。这些系统建设得都非常好&#xff0c;无论是业务的切合度&#x…

pytorch 深度学习之余弦相似度

文章目录 用处定理代码F.normalize() 和 F.norm() 的区别 用处 此方法特别重要&#xff0c;经常可以用来修改论文&#xff0c;提出创新点. 定理 余弦相似度是通过计算两个向量之间的夹角余弦值来衡量它们的相似性。给定两个非零向量 x 和 y&#xff0c;它们之间的余弦相似度…

python科研绘图:带正态分布的直方图

带正态分布的直方图是一种用直方图表示数据分布的图表&#xff0c;其中数据经过了正态分布的拟合。正态分布是一种常见的概率分布&#xff0c;具有平均值和标准差。在带正态分布的直方图中&#xff0c;数据被分成不同的区间&#xff0c;每个区间的频数或频率可以用颜色或标签表…

手撕无头单链表

&#x1f493; 博客主页&#xff1a;江池俊的博客⏩ 收录专栏&#xff1a;数据结构探索&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f525;编译环境&#xff1a;Visual Studio 2022&#x1f38…

YOLOv5项目实战(3)— 如何批量命名数据集中的图片

前言:Hello大家好,我是小哥谈。本节课就教大家如何去批量命名数据集中的图片,希望大家学习之后可以有所收获!~🌈 前期回顾: YOLOv5项目实战(1)— 如何去训练模型 YOLOv5项目实战(2࿰

PTA 7-24 求素数

本题目要求读入1个正整数A&#xff0c;判断A是否为素数。 小贴士&#xff1a;反过来考虑&#xff0c;只要有一次整除了&#xff0c;就不是素数&#xff0c;循环break&#xff0c;不要继续算了。还可以加入标志法&#xff0c;flag的初值为1&#xff0c;一,旦整除了&#xff0c;…

折爱心教程(简单版本)

文章目录 1.折出双三角形2.向中心折叠3.形成正方形4.对折正反面相同5.向中心折6.外侧角向中心折7.顶部三角形向下折叠注意参考资料 我怎么也没有想到&#xff0c;身为混迹职场多年的老油子&#xff0c;竟然还能遇到折纸这种硬性task。 可是给的教程步骤省略太多了&#xff0c;看…

Linux进程间通信模式

管道是一种单向传输数据的机制&#xff0c;它其实是一段缓存&#xff0c;里面的数据只能从一端写入&#xff0c;从另一端读出。如果想互相通信&#xff0c;我们需要创建两个管道才行。 管道分为两种类型&#xff0c;“|” 表示的管道称为匿名管道&#xff0c;意思就是这个类型…