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

结论先行:

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.hqwc.cn/news/180338.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法训练营第五十一天|309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费

第九章 动态规划part12 309. 买卖股票的最佳时机含冷冻期 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xff08;多次买卖一支股票&…

Uniapp-小程序自定义导航栏

一、项目背景 制作小程序页面时候发现原生导航栏有一定的高度是没有背景渲染的会出现这种情况 但是我们需要的是 二、原因 小程序的原生导航栏存在。一般可以使用 纯色填充顶部栏 可以直接使用navigationBarBackgroundColor完成 在style中添加 "navigationBarBackgrou…

JJJ:python学习笔记

p4 没有编译的过程 源码和输入得到输出 静态语言&#xff1a;编译型 脚本语言&#xff1a;解释型 p5 又叫做胶水语言 p7 p8 p10

91.移动零(力扣)

问题描述 代码解决以及思想 class Solution { public:void moveZeroes(vector<int>& nums) {int left 0; // 左指针&#xff0c;用于指向当前非零元素应该放置的位置int right 0; // 右指针&#xff0c;用于遍历数组int len nums.size(); // 数组长度while …

Postman内置动态参数以及自定义的动态参数

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一&#xff09;内置动态参数 {{$timestamp}} 生成当前时间的时间戳{{$randomInt}} 生成0-1000之间的随机数{{$guid}} 生成随…

IDEA没有Add Framework Support解决办法

点击File—>Settings 点击第一个设置快捷键 点击apply和ok即可 我们要点击一下项目&#xff0c;再按快捷键ctrlk 即可

javaweb---maventomcat使用教程

文章目录 今日内容0 复习昨日1 Maven1.0 引言1.1 介绍1.2 下载1.3 安装1.3.1 解压1.3.2 配置环境变量1.3.3 测试 1.4 仓库1.5 Maven配置1.5.1 修改仓库位置1.5.2 设置镜像 2 IDEA - MAVEN2.1 idea关联maven2.2 创建java项目2.3 java项目结构2.4 pom2.5 导入依赖2.5.1 查找依赖2…

氢原子波函数等概率面的绘制

氢原子波函数等概率面的绘制 归一化后的氢原子波函数

c语言:如何打印杨辉三角形。

题目&#xff1a;打印杨辉三角形 如&#xff1a; 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 思路和代码&#xff1a; //由规律不难得出&#xff0c;每行首个数字和最后最后一个数字都为1&#xff0c;其余数字是这列的上一个数字和前一个数字的和组成&#xff0c;由此推出代码 #de…

Day31力扣打卡

打卡记录 由子序列构造的最长回文串的长度&#xff08;区间DP&#xff09; 先将两个字符串合并&#xff0c;再仿照 最长回文子序列 的做法&#xff0c;从中间开始往外进行遍历&#xff0c;由于是两个字符串&#xff0c;在 最长回文子序列 的做法上需要满足 len(word1) < j …

解决:java: 错误: 不支持发行版本 5 最有效方法

报错信息如图&#xff1a; 直接上终极方法&#xff1a; 修改配置文件 如图找到settings.xml文件 在标签中间插入如下代码&#xff08;jdk更改为自己电脑上的版本&#xff09; <profile><id>development</id><activation><jdk>11</jdk><…

MySQL表的增查(进阶)

目录 1.插入查询结果 2.查询 2.1聚合查询 2.1.1聚合函数 2.1.2GROUP BY子句 2.1.3HAVING 2.2联合查询 2.2.1内连接 2.2.2外连接 2.2.3自连接 2.3子查询 2.4合并查询 1.插入查询结果 在一张表中插入另一张表的查询结果。 语法为&#xff1a; insert into 表名 (列…