vue组件深入介绍之插槽

了解插槽之前请先了解vue组件基础及注册

Vue2官网介绍
Vue3官网介绍

1、vue2插槽介绍

在2.6.0中,具名插槽和作用域插槽引入了一个新的统一语法(v-slot指令)。它将取代slot和slot-scope;

Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将 < slot > 元素作为承载分发内容的出口。

允许父组件更改子组件模板内容,例如:

//父组件
<navigation-link url="/profile">
  Your Profile
</navigation-link>
//子组件NavigationLink.vue
<a v-bind:href="url" class="nav-link">
  <slot></slot>
</a>
//渲染结果
<a href="/profile" class="nav-link">
  Your Profile
</a>

如果 < navigation-link > 的 template 中没有包含一个 < slot > 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃。

/*子组件*/
<template>
<a v-bind:href="url" class="nav-link"></a>
</template>
/*父组件*/
<navigation-link url="/profile">
 	<span> Your Profile</span>a标签
</navigation-link>
//渲染结果,a标签中间无任何内容被渲染,span以及文本均被抛弃
<a href="/profile" class="nav-link">
</a>

2、vue3插槽介绍

//子组件
<script setup>
</script>

<template>
	<button><slot></slot></button>
</template>
//父组件
<script setup>
import {ref} from 'vue';
import MyButton from '@/components/MyButton.vue'
</script>

<template>
	<div class="index-main">
		<MyButton>点击<span style="display: inline-block; width:10px; height: 10px; border-radius: 50%; background-color: #f00; margin-left: 5px;"></span></MyButton>
		-->
	</div>
</template>
/*渲染结果*/
<button>点击<sapn data-v-b4e148ca="" style="display: inline-block; width: 10px; height: 10px; border-radius: 50%; background-color: rgb(255, 0, 0); margin-left: 5px;"></sapn></button>

插槽内容可以是任意合法的模板内容,不局限于文本;可以传入多个元素,甚至是组件

3、插槽渲染作用域

vue2和vue3插槽作用域须知如下:
父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

/*父组件,父组件中的msg属性在父组件和子组件中均可渲染,但在MyButton子组件中无法获取msg的值,只有使用props传值后才可获取到*/
<script setup>
import {ref} from 'vue';
import MyButton from '@/components/MyButton.vue'

const msg = ref('提交');
</script>

<template>
	<div class="index-main">
		<div>{{msg}}</div>
		<MyButton>{{msg}}</MyButton>
	</div>
</template>

4、插槽的默认值设置

4.1、Vue2参考插槽——后备内容

/*vue2子组件设置默认值*/
<template>
<a v-bind:href="url" class="nav-link">
	 <slot>跳转链接</slot>
</a>
</template>

4.2、Vue3参考插槽——默认内容

/*vue3子组件设置默认值*/
<script setup>
</script>

<template>
	<button>
		<slot>提交</slot>
	</button>
</template>
/*vue3 父组件*/
<template>
	<div class="index-main">
		<!-- 按钮文本为 提交 -->
		<MyButton></MyButton>
		<!-- 按钮文本为 立即提交 -->
		<MyButton>立即提交</MyButton>
	</div>
<template>

5、具名插槽

简单来说,当子组件有多个插槽时,为每个插槽设置不同名字,父组件中引用时可根据名字修改不同的插槽内容;

5.1、vue2具名插槽介绍

自 2.6.0 起有所更新。已废弃的使用 slot attribute;已废弃slot属性的用法具体请查看官网;

子组件插槽新语法:< slot>元素,此元素用油一个特殊的属性name,用name来定义额外的插槽;

一个不带 name 的 出口会带有隐含的名字“default”。

/*base-layout子组件*/
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

父组件使用时:
可以在一个 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称:

注意 v-slot 只能添加在 上;只有一种特殊情况,可暂不了解;

跟 v-on 和 v-bind 一样,v-slot 也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header:

/*父组件*/
<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <!-- 
    更明确的写法
	<template v-slot:default>
	     <p>A paragraph for the main content.</p>
	     <p>And another one.</p>
	</template>
  -->
	 
  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

新语法与vue3相同,具体示例不再冗余展示;具体示例请参照vue3;将对应的props传值修改为vue2写法即可;

5.2、Vue3具名插槽介绍

子组件包含多个插槽时:
< slot> 元素可以有一个特殊的 attribute name,用来给各个插槽分配唯一的 ID;
这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 出口会隐式地命名为“default”

父组件的使用介绍:
要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 < template> 元素,并将目标插槽的名字传给该指令;
v-slot 有对应的简写 #,因此 < template v-slot:left> 可以简写为 <template #left>

示例参考

/*vue3 定义一个列表组件ListChild.vue,左侧图标,右侧箭头*/
<template>
	<div class="list-bar" title="标题">
		<div v-if="leftShow" class="list-left">
			<slot name="left">
				<div class="list-leftIcon"></div>
			</slot>
		</div>
		<div class="list-middle">
			<slot>列表内容</slot>
		</div>
		<div v-if="rightShow" class="list-rightIcon">
			<slot name="right">&gt;</slot>
		</div>
	</div>
</template>

<script setup>
const props = defineProps({
	leftShow:{
		type: Boolean,
		default: true
	},
	rightShow:{
		type: Boolean,
		default: true
	}
});
</script>

<style scoped>
	.list-bar{
		display: flex;
		display: -webkit-flex;
		align-items: center;
		-webkit-align-items: center;
	}
	.list-left{
		margin-right: 8px;
	}
	.list-leftIcon{
		width: 4px;
		height: 4px;
		background: #f00;
	}
	.list-rightIcon{
		margin-left: 10px;
	}
</style>
/*父组件*/
<script setup>
import ListChild from '@/components/ListChild.vue'
</script>

<template>
	<div class="index-main">
		<!-- 使用默认效果 -->
		<ListChild></ListChild>
		<!-- 修改右侧内容 -->
		<ListChild>
			<template v-slot:right>
				<!-- v-sole冒号后面为插槽的name -->
				<!--  中间为重新定义的左侧内容  -->
				<span style="color: #999; font-size: 12px;">2023-01-01</span>
			</template>
		</ListChild>
		<!-- 修改左侧及主体内容 -->
		<ListChild>
			<template #left>
				<span style="color: #999; font-size: 12px;">2023-01-01</span>
			</template>
			<!-- 默认不带name的均为默认插槽内容,是否 -->
			<!-- <div>主体内容修改</div> -->
			<template #default>主体内容</template>
		</ListChild>
	</div>
</template>

展示效果如下:
在这里插入图片描述

5.3、具名插槽内容替换图解

在这里插入图片描述

6、Vue3条件插槽

当需要根据插槽是否存在来判断某些内容时,可以结合$slots 属性与 v-if 来实现。(vue3独有特点)

在下面的示例中,我们定义了一个卡片组件,它拥有三个条件插槽:header、footer 和 default。 当 header、footer 或 default 存在时,我们希望包装它们以提供额外的样式:

<template>
  <div class="card">
    <div v-if="$slots.header" class="card-header">
      <slot name="header" />
    </div>
    
    <div v-if="$slots.default" class="card-content">
      <slot />
    </div>
    
    <div v-if="$slots.footer" class="card-footer">
      <slot name="footer" />
    </div>
  </div>
</template>

7、作用域插槽

备注:自 2.6.0 起有所更新。Vue2已废弃的使用 slot-scope;vue2和vue3的语法一致;但下面的示例为VUE3的组合式写法;

在插槽的渲染作用域中我们提到,插槽的内容无法访问到子组件的状态;

但是某些场景下可能需要父组件域内和子组件域内均能访问到此数据;此时我们需要让子组件渲染时将部分数据提供给插槽,以便父组件可以获取到;

7.1、默认插槽作用域插槽的设置

实现方法:将子组件的插槽设置一个属性;
如下面ListChild.vue子组件中slot标签上的count和list属性;也可直接使用v-bind绑定对象

父组件中写法:
v-slot=“slotProps”
v-slot:default=“slotProps”
缩写:
#default=“slotProps”
解构插槽:
v-slot=“{子组件属性名}”

/*子组件ListChild.vue*/
<template>
	<div class="list-bar">
		<slot :count="1" :list="listVal" v-bind="{a:1,b:2}">列表内容</slot>
	</div>
</template>
<script setup>
	import { ref } from 'vue';
	const listVal = ref('列表主题内容');
</script>
/*父组件index.vue*/
<script setup>
	import { ref } from 'vue';
</script>
<template>
	<div class="index-main">
		<!-- 
		slotProps可自定义名称
		slotProps的值为子组件slot标签上的所有自定义属性的对象合集{ "count": 1, "list": "列表", "a": 1, "b": 2 }
		-->
		<ListChild v-slot="slotProps">
			{{slotProps.count}}--{{slotProps.list}}--{{slotProps.a}}--{{slotProps.b}}
		</ListChild>
		<!-- 使用解构赋值 -->
		<ListChild v-slot="{count,list,a,b}">
			{{count}}--{{list}}--{{a}}--{{b}}
		</ListChild>
		<!-- 使用解构赋值,属性名重命名 -->
		<ListChild v-slot="{count:countCopy ,list}">
			{{countCopy }}--{{list}}
		</ListChild>
	</div>
</template>

7.2、具名作用域插槽

具名作用域插槽的工作方式也是类似的,插槽 props 可以作为 v-slot 指令的值被访问到;

父组件中写法:
v-slot:name=“slotProps”
缩写:
#name=“slotProps”

注意插槽上的 name 是一个 Vue 特别保留的 attribute,不会作为 props 传递给插槽。因此最终 slotProps 的结果是 { “count”: 1, “list”: “列表主题内容” }

/*子组件ListChild.vue*/
<template>
	<div class="list-bar">
		<slot name="label" :count="1" :list="listVal">列表内容</slot>
	</div>
</template>
<script setup>
	import { ref } from 'vue';
	const listVal = ref('列表主题内容');
</script>
/*父组件index.vue*/
<ListChild v-slot:label="slotProps">
	{{slotProps}}
</ListChild>

注意要点:

  1. 当只有一个默认插槽时,可以把v-slot直接用在组件上;
  2. 默认插槽的缩写语法不能和具名插槽混用,因为它会导致作用域不明确:
  3. 只要出现多个插槽,请始终为所有的插槽使用完整的基于 的语法;

8、动态插槽名

动态指令参数在 v-slot 上也是有效的;也可简写;具体使用方法如下

/*子组件*/
<template>
	<div class="list-bar" title="标题">
		<div v-if="leftShow" class="list-left">
			<slot name="left">
				<div class="list-leftIcon"></div>
			</slot>
		</div>
		<div class="list-middle">
			<slot>列表内容</slot>
		</div>
		<div v-if="rightShow" class="list-rightIcon">
			<slot name="right">&gt;</slot>
		</div>
	</div>
</template>
/*父组件index.vue*/
<script setup>
import {ref} from 'vue';
const dynamicSlotName = ref('left');
setTimeout(()=>{
	dynamicSlotName.value = 'right';
},1000)
</script>
<template>
	<div>
		<ListChild :listData="listData" prop="title">
			<template v-slot:[dynamicSlotName]>1111</template>
		</ListChild>
	</div>
</template>

vue2官方文档未提及缩写写法,建议采用v-slot的写法定义动态插槽名;
Vue3可使用如下缩写写法;

/*缩写写法*/
<template #[dynamicSlotName]>1111</template>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从直播消息中找到对应的proto协议内容

这么多直播间的消息&#xff0c;我们该怎么从里面找到我们需要的消息定义呢&#xff1f; 其实只要你能找到这个里面的this对象&#xff0c;就可以看到这个对象上面有一个root > webcast > im 这里面的函数就都是用于解析直播间消息的函数&#xff1a; 想要看一下每个消息…

做工作室项目重要还是运营重要

做工作室项目重要还是运营重要&#xff0c;先说答案&#xff0c;项目好是基础&#xff0c;然后才能谈运营&#xff01; 90%的工作室活不过一年&#xff0c;这句话是有数据支撑的&#xff0c;因为就工商注册的公司而言&#xff0c;一年内倒闭的就是这么个数据&#xff0c;所以工…

grpc学习golang版( 六、服务器流式传输 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件三、拷贝任意文件进项目四、编写serve…

【C++ | 继承】|概念、方式、特性、作用域、6类默认函数

继承 1.继承的概念与定义2.继承的方式2.1继承基本特性2.2继承的作用域2.2.1隐藏赋值兼容 派生类的创建和销毁构造函数拷贝构造赋值重载 1.继承的概念与定义 继承是面向对象编程中的一个重要概念。它的由来可以追溯到软件开发中的模块化设计和代码复用的需求。 在软件开发过程…

网络爬虫(一)

1. 深度优先爬虫&#xff1a;深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始&#xff0c;先访问一个链接&#xff0c;然后再访问该链接下的链接&#xff0c;一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接&#xff0c;再继续深入访问下一个未被访…

2024年数据和AI趋势报告深度解析:洞悉未来,引领变革

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;和大数据技术正以前所未有的速度重塑着我们的工作和生活方式。Google Cloud发布的《2024年数据和AI趋势报告》为我们提供了一个窗口&#xff0c;让我们得以窥见未来几年内这些技术可能带来的变革。本文将深…

Dev++软件连接Sqlite

Dev中的C语言使用连接sqlite数据库 1.下载sqlite3.dll和sqlite3.h sqlite3.dll类似于.c文件&#xff0c;封装了函数的原型。 sqlite3.h库文件声明函数。 官网地址下载&#xff1a;sqlite sqlite-amalgamation-3460000.zipsqlite-dll-win-x64-3460000.zip 2.新建c项目 1. …

【python】最新版抖音s逆向拿到数据,非常详细教程(附完整代码)

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

服务器数据恢复—EVA存储RAID管理信息丢失的数据恢复案例

意外断电导致raid硬件损坏或者riad管理信息丢失等raid模块损坏而导致数据丢失的情况非常普遍。正常情况下&#xff0c;磁盘阵列一旦创建完成就不会再对管理模块中的信息进行更改&#xff0c;但是raid管理模块中的信息属于可修改信息&#xff0c;一次或多次的意外断电可能会导致…

互联网场景下人脸服务解决方案优化设计

1.简介 1.1目的 在过去的一段时间里&#xff0c;因为听见科技业务对人脸服务的需求&#xff0c;所有针对互联网视频中关键人物定位的检索任务&#xff0c;进行了基于互联网场景的人脸基线服务的构建。本文档是针对当前基线解决方案进行优化的方案设计文档。 1.2范围 本文档描述…

2024 全球软件研发技术大会来了!NineData创始人CEO叶正盛将分享《云原生实时数据复制技术原理与实践》主题演讲

2024年7月4-5日&#xff0c;由 CSDN 和 Boolan 联合主办的「2024 全球软件研发技术大会&#xff08;SDCon&#xff09;」将在北京威斯汀酒店举行&#xff0c;将成为引领行业迈向 AI 2.0 时代的重要桥梁。NineData 创始人&CEO叶正盛受邀参会&#xff0c;并将带来《云原生实时…

怎么采集天猫的商品或店铺数据

怎么使用简数采集器批量采集天猫的商品或店铺相关信息呢&#xff1f; 简数采集器暂时不支持采集天猫的商品或店铺相关数据&#xff0c;只能采集页面公开显示的信息&#xff0c;谢谢。 简数采集器抓取网页数据特别简单&#xff0c;不需要懂技术写代码&#xff0c;只需填写网址…

ROS2用c++开发参数节点通信

1.创建节点 cd chapt4/chapt4_ws/ ros2 pkg create example_parameters_rclcpp --build-type ament_cmake --dependencies rclcpp --destination-directory src --node-name parameters_basic --maintainer-name "joe" --maintainer-email "1027038527qq.com&…

大数据开发助手:Coze平台上一款致力于高效解决大数据开发问题的智能Bot!

大数据开发助手&#xff1a;Coze平台上一款致力于高效解决大数据开发问题的智能Bot 核心技术揭秘1. **自然语言处理&#xff08;NLP&#xff09;**2. **知识图谱构建**3. **个性化推荐算法** 功能特色概览1. **即时问题解答**2. **最佳实践分享**3. **个性化学习路径**4. **社区…

在 CentOS 上安装 Docker Engine

前言 Docker 是啥之类的就不必多说了&#xff0c;直接上安装步骤。 官网安装教程地址&#xff1a;https://docs.docker.com/engine/install/centos/ 1.Uninstall old versions &#xff08;卸载旧版本&#xff09; Older versions of Docker went by docker or docker-engin…

error LNK2019: 无法解析的外部符号 _SDL_main,该符号在函数 _main_getcmdline 中被引用

VC MFC情况下出现此问题&#xff0c; 网上搜索了很多文章无法解决。 error LNK2019: 无法解析的外部符号 _SDL_main&#xff0c;该符号在函数 _main_utf8 中被引用_sdl2main.lib出现无法解析的外部符号-CSDN博客 字符集必须设置为&#xff1a;

【Android面试八股文】性能优化相关面试题: 什么是内存抖动?什么是内存泄漏?

文章目录 一、什么是内存抖动?内存抖动的问题卡顿OOM(Out Of Memory)二、什么是内存泄漏(Memory Leak)?引用计数法可达性分析法一、什么是内存抖动? 在Java中,每创建一个对象,就会申请一块内存,存储对象信息; 每分配一块内存,程序的可用内存也就少一块; 当程序…

SwiftUI八与UIKIT交互

代码下载 SwiftUI可以在苹果全平台上无缝兼容现有的UI框架。例如&#xff0c;可以在SwiftUI视图中嵌入UIKit视图或UIKit视图控制器&#xff0c;反过来在UIKit视图或UIKit视图控制器中也可以嵌入SwiftUI视图。 本文展示如何把landmark应用的主页混合使用UIPageViewController和…

VaRest插件常用节点以及Http请求数据

1.解析json &#xff08;1&#xff09;Construct Json Object&#xff1a;构建json对象 &#xff08;2&#xff09;Decode Json&#xff1a;解析json 将string转换为json &#xff08;3&#xff09;Encode json&#xff1a;将json转换为string &#xff08;4&#xff09;Get S…

非标设备行业的数智化项目管理

近年来&#xff0c;中国制造快速发展&#xff0c;企业迫切需要加快转型升级。与传统制造业相比&#xff0c;高端制造业具有明显的优势&#xff1a;高技术、高附加值、低污染、低排放、竞争优势强。一方面&#xff0c;企业对于生产效率和自动化水平的要求不断提高&#xff0c;期…