【vue】14.插槽:构建可复用组件的关键

今天看代码的时候碰到了插槽,有些看不懂,所以写下这篇文章,系统地梳理一下关于插槽的内容,也希望给大家带来一些帮助。

// 我碰到的插槽长这样
<template  #default="scope">... 
</template>


一.什么是插槽?

根据 Vue 官方的定义:“插槽用于向子组件传递内容。和 prop 用于传递数据不同,插槽用于传递更丰富的内容,包括 HTML 元素和其他 Vue 组件。”

简单来说,插槽就像是组件预留的“空位”,允许向组件内部插入任何内容,无论是文本、HTML 元素还是其他组件。有了插槽组件更加灵活,可以根据不同的使用场景展示不同的内容。

听起来有点抽象,没关系,举个例子一下就懂了。

现在有一个界面,它是由许多个卡片组件构成的。我们称界面为父组件,卡片组件为子组件,如图:

先看看子组件和父组件的代码:

// 卡片组件  子组件
<template><div class="card"><slot name="header"></slot><slot name="image"></slot></div>
</template>
// 在父组件中使用子组件
<CardComponent><template #header><h2>vue</h2></template><template #image><img src="vue.jpg" alt="vue"></template></template>
</CardComponent><CardComponent><template #header><h2>react</h2></template><template #image><img src="react.jpg" alt="react"></template></template>
</CardComponent>// 后两个类似,省略

卡片组件包含标题和图片两部分,但其具体内容是由使用该组件的父组件决定的。那么,父组件如何知道内容应该传递到何处,以及如何进行传递呢?

传递到何处:

子组件通过定义带有特定名称的插槽来预留内容位置。例如,一个用于标题的插槽可以如下表示:

<slot name="header"></slot>

name="header" 属性定义了一个名为 header 的插槽。

如何传递:

父组件需要将要传递的内容包裹在 <template> 标签内,并通过 # 符号后跟插槽名称来指定内容的插入位置。例如,要将标题传递到名为 header 的插槽,可以这样做:

<template #header><h2>这是卡片标题</h2>
</template>

这样,父组件就能精确地将内容传递到子组件中预定的插槽位置。


二.插槽的种类及其具体使用

理解了插槽是什么后,我们来看看不同类型的插槽。Vue 3 主要有三种插槽:具名插槽、条件插槽、作用域插槽。

1.默认插槽

默认插槽也叫匿名插槽,是最简单的插槽形式。不需要为 <slot> 标签提供 name 属性,并且在使用组件时,也不需要在 <template> 上指定插槽名称。如果一个组件只包含一个插槽,那我们就可以使用默认插槽。

毕竟只有一个坑,不管你给不给这个坑起名字,传进去的萝卜都只能待这个坑。所以没必要给坑起名字,也没必要给要传进去的萝卜指定坑位,一个萝卜一个坑,直接传就行了。

如上图所示,你可以为插槽指定默认内容,就像这样:

<!-- child.vue -->
<template><div><slot>默认萝卜</slot></div>
</template>

现在,当在父组件中使用 <child> 且没有提供任何插槽内容时,就会渲染“默认萝卜”。

但是,如果父组件提供了插槽内容,那么子组件的默认内容就会被替换掉。

// 在父组件中使用子组件
<child>我是父组件传递的萝卜,我会取代之前的默认萝卜</child>

父萝卜驾到,通通闪开!


2.具名插槽

具名插槽,顾名思义,具有名字的插槽,也就是带“name”属性的插槽。

<slot> 元素可以有一个特殊的属性name,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容。

如果我们需要给一个组件的多处地方填充内容,那么具名插槽就有用了。本文刚开始引入的卡片例子,就使用了具名插槽。

本质上是多个萝卜多个坑的问题。要怎么实现把萝卜放进对应的坑里?首先给坑位起名字,然后告诉萝卜,你要去哪个坑,就好了。

再举一个例子:

// 在父组件中使用子组件
<child><template #header><h1>我是标题</h1></template><template #default><p>我是第一段话</p><p>我是第二段话</p></template><template #footer><p>我是底部信息</p></template>
</child>
// 子组件
<div><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer></div>

上面带name属性的就是具名插槽,如果不带name,那么那么它的name默认为default。当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 <template> 节点都被隐式地视为默认插槽的内容。

所以上面的父组件也可以写成:

// 在父组件中使用子组件
<child><template #header><h1>我是标题</h1></template><p>我是第一段话</p><p>我是第二段话</p><template #footer><p>我是底部信息</p></template>
</child>

如果你要把多个萝卜放入多个坑里,知道自己要去哪个坑的萝卜就会自己找到对应name的坑进去,其他的萝卜都进入默认的坑。


3.作用域插槽

(1)渲染作用域

在了解作用域插槽之前,有必要了解一下“渲染作用域”。

vue官网对“渲染作用域”的描述:

插槽内容可以访问到父组件的数据作用域,因为插槽内容本身是在父组件模板中定义的。举例来说:

<span>{{ message }}</span>
<FancyButton>{{ message }}</FancyButton>

这里的两个 {{ message }} 插值表达式渲染的内容都是一样的。

插槽内容无法访问子组件的数据。Vue 模板中的表达式只能访问其定义时所处的作用域,这和 JavaScript 的词法作用域规则是一致的。换言之:

父组件模板中的表达式只能访问父组件的作用域;子组件模板中的表达式只能访问子组件的作用域。

在 Vue 中,组件的作用域规则是这样的:

  • 父组件模板中的所有内容都是在父组件的作用域中编译的。在父组件模板中,可以访问父组件的数据和方法。
  • 子组件模板中的所有内容都是在子组件的作用域中编译的。在子组件模板中,可以访问子组件的数据和方法。

插槽内容也是如此:

  • 当在父组件中使用子组件并定义插槽内容时,这些插槽内容是在父组件的作用域中编译的。因此,可以在插槽内容中使用父组件的数据和方法,但不能直接使用子组件的数据和方法。
  • 子组件可以通过 props 接收来自父组件的数据,但是插槽内容本身不能直接访问子组件的数据。

那如果我们需要在插槽内容中使用子组件的数据呢?

那就要用到“作用域插槽”了。

(2)默认作用域插槽

在子组件slot标签绑定属性,然后在父组件中用v-slot进行接收,就可以把数据传递给父组件中。

在接收方式上,默认插槽和具名插槽有一些不同,先来看看默认插槽如何接收子组件传过来的props:

//子组件
<template><div><slot personName="清清" age="3"></slot></div>
</template>//父组件<template><div><Child v-slot="slotProps">我是 {{ slotProps.personName }} ,我今年 {{ slotProps.age }} 岁了。</Child></div>
</template>
<script setup>
import Child from './Child.vue'
</script>

这里的slotProps是插槽 prop 的名字,可以自定义,方便后面使用。

也可以接收响应式数据:

(3)具名作用域插槽

具名作用域插槽允许给插槽起个名字,并且可以通过 v-slot:插槽名字="slotProps" 的方式来接收子组件传递的数据。如果用缩写的话,可以写成 #插槽名字="slotProps"

<MyComponent><template #header="headerProps">{{ headerProps }}</template><template #default="defaultProps">{{ defaultProps }}</template><template #footer="footerProps">{{ footerProps }}</template>
</MyComponent>

子组件传递数据给插槽::

<slot name="header" message="hello"></slot>

插槽的 name 是 Vue 保留的属性,不会作为数据传递给插槽。所以,父组件拿到的headerProps,它只会包含 { message: 'hello' }

(4)注意事项

如果同时使用了具名插槽和默认插槽,那么需要为默认插槽明确地使用 <template> 标签。如果不这样做,可能会出现编译错误,因为这样容易混淆哪个数据属于哪个插槽。

举个例子,有一个组件 MyComponent,它有一个默认插槽和一个名为 footer 的具名插槽,我们不能直接在组件上使用 v-slot 指令,这样会导致数据的作用域不清楚。

所以,我们应该这样做:

<MyComponent><!-- 明确地使用默认插槽 --><template #default="{ message }"><p>{{ message }}</p></template><!-- 具名插槽 --><template #footer><p>这里有一些联系信息</p></template>
</MyComponent>

这样的话, message 只在默认插槽中可用,而在 footer 插槽中不可用。这样代码更清晰,也更不容易出错。

通过上述例子,我们可以看到插槽在 Vue 3 中的强大之处。它们不仅使组件更加灵活,还极大地提高了组件的可复用性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460146.html

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

相关文章

Java项目实战II基于Spring Boot的美食烹饪互动平台的设计与实现(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当今美食…

ssm基于ssm框架的滁艺咖啡在线销售系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码请私聊我 需要定制请私聊 目 录 第1章 绪论 1 1.1选题动因 1 1.2目的和意义 1 1.3论文结构安排 2 第2章 开发环境与技术 3 2.1 MYSQ…

echarts实现 水库高程模拟图表

需求背景解决思路解决效果index.vue 需求背景 需要做一个水库高程模拟的图表&#xff0c;x轴是水平距离&#xff0c;y轴是高程&#xff0c;需要模拟改水库的形状 echarts 图表集链接 解决思路 配合ui切图&#xff0c;模拟水库形状 解决效果 index.vue <!--/*** author:…

引入RFID技术,焕新消防应急物资管理方式

智能化应急消防管理系统在现代消防工作中扮演着至关重要的角色&#xff0c;引入射频识别&#xff08;RFID&#xff09;技术&#xff0c;并根据消防设备管理的具体状况及需求&#xff0c;广州一芯未来研发了一套RFID消防设备管理系统。 一、射频识别技术RFID简述 射频识别技术RF…

软件压力测试有多重要?北京软件测试公司有哪些?

软件压力测试是一种基本的质量保证行为&#xff0c;它是每个重要软件测试工作的一部分。压力测试是给软件不断加压&#xff0c;强制其在极限的情况下运行&#xff0c;观察它可以运行到何种程度&#xff0c;从而发现性能缺陷。 在数字化时代&#xff0c;用户对软件性能的要求越…

正式入驻!上海斯歌BPM PaaS管理软件等产品入选华为云联营商品

近日&#xff0c;上海斯歌旗下BPM PaaS管理软件&#xff08;NBS&#xff09;等多款产品入选华为云云商店联营商品&#xff0c;上海斯歌正式成为华为云联营商品合作伙伴。用户登录华为云云商店即可采购上海斯歌的BPM PaaS产品及配套服务。通过联营模式&#xff0c;双方合作能够深…

「Mac畅玩鸿蒙与硬件7」鸿蒙开发环境配置篇7 - 使用命令行工具和本地模拟器管理项目

本篇将讲解在 macOS 上配置 HarmonyOS 开发环境的流程&#xff0c;聚焦 hvigorw 命令行工具的使用。我们将以创建 HelloWorld 项目为例&#xff0c;演示使用 hvigorw 进行项目构建、清理操作&#xff0c;并通过 DevEco Studio 的本地模拟器进行预览&#xff0c;帮助提升项目开发…

ECharts饼图,配置标注示例

const color ["#00FFB4", "#5498FD", "#6F54FD", "#FD5454", "#FDA354",]const datas [{ value: 100, name: "一年级" },{ value: 70, name: "二年级" },{ value: 184, name: "三年级" },{…

基于卷积神经网络的苹果病害识别与防治系统,resnet50,mobilenet模型【pytorch框架+python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 苹果病害识别与防治系统&#xff0c;卷积神经网络&#xff0c;resnet50&#xff0c;mobilenet【pytorch框架&#xff0c;python源码】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于卷积…

YOLO即插即用模块---CAA

oly Kernel Inception Network for Remote Sensing Detection 论文地址&#xff1a;2403.06258https://arxiv.org/pdf/2403.06258 主要问题&#xff1a; 目标尺度变化大&#xff1a; 遥感图像中目标尺度范围广泛&#xff0c;从大型物体&#xff08;如足球场&#xff09;到小型…

【网络面试篇】TCP与UDP类

目录 一、综述 1. TCP与UDP的概念 2. 特点 3. 区别 4. 对应的使用场景 二、补充 1. 基础概念 &#xff08;1&#xff09;面向连接 &#xff08;2&#xff09;可靠的 &#xff08;3&#xff09;字节流 2. 相关问题 &#xff08;1&#xff09;TCP 和 UDP 可以同时绑定…

【C++】类和对象(六):运算符重载1

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C的运算符重载&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 (A) 引入(B) 运算符重载 (A) 引入 写一个Date日期类&#xff0c;问&#xff1a;如果我…

C语言(一维数组)

如果对你有帮助&#xff0c;请点个免费的赞吧&#xff0c;谢谢汪。&#xff08;点个关注也可以&#xff01;&#xff09;\n\n如果以下内容需要补充和修改&#xff0c;请大家在评论区交流~ 思维导图 1.数组 由一个或多个相同的数据类型组成的集合 特点&#xff1a; 数据类型相…

Mount Image Pro,在取证安全的环境中挂载和访问镜像文件内容

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据恢复、数据备份解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 天津鸿萌科贸发展有限公司是 GetData 公司数据恢复与取证工…

上市公司企业数字金融认知数据集(2001-2023年)

一、测算方式&#xff1a;参考C刊《经济学家》王诗卉&#xff08;2021&#xff09;老师的做法&#xff0c;数字金融认知使用每万字年报描述中包含的对数字金融相关关键词的提及次数&#xff0c;关键词为&#xff1a;互联网、数字化、智能、大数据、电子银行、金融科技、科技金融…

【Mybatis】动态SQL+配置文件+数据库连接池+企业规范(10)

本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 目录 本系列共涉及4个框架&#xff1a;Sping,SpringBoot,Spring MVC,Mybatis。 博客涉及框架的重要知识点&#xff0c;根据序号学习即可。 …

Web3的去中心化社交网络:区块链技术如何改变互动方式

随着互联网技术的不断进步&#xff0c;社交网络正在经历一场深刻的变革。Web3&#xff0c;作为新一代互联网技术的代表&#xff0c;正通过区块链和去中心化理念改变着我们与他人互动的方式。传统的社交网络通常由大型公司控制&#xff0c;用户数据的集中化管理和隐私问题备受关…

大数据-191 Elasticsearch - ES 集群模式 配置启动 规划调优

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

短信登录的实现-redis和session的比较

目录 短信登录功能的实现一&#xff1a;基于session进行短信登录1&#xff1a;发送验证码2&#xff1a;登录3&#xff1a;登录验证拦截器4&#xff1a;隐藏用户敏感信息二&#xff1a;session的集群共享问题三&#xff1a;基于redis实现短信登录登录的刷新问题 短信登录功能的实…

中欧科学家论坛暨第六届人工智能与先进制造国际会议(AIAM 2024)在德国法兰克福成功举办,两百余名中外科学家共襄盛举

2024年10月20至21日&#xff0c;首届中欧科学家论坛在德国法兰克福的SAALBAU Titus Forum国际会议中心成功举行。中国驻法兰克福总领事馆伍鹏飞副总领事、德国兰斯巴赫-鲍姆巴赫市市长Michael Merz亲自出席并致辞。2004年诺贝尔化学奖得主Aaron Ciechanover教授和法国国家科学院…