vue组件深入介绍之插槽

news2024/10/7 6:45:36

了解插槽之前请先了解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.coloradmin.cn/o/1890384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

等保2.0 实施方案之信息软件验证要求

一、等保2.0背景及意义 随着信息技术的快速发展和网络安全威胁的不断演变&#xff0c;网络安全已成为国家安全、社会稳定和经济发展的重要保障。等保2.0&#xff08;即《信息安全技术 网络安全等级保护基本要求》2.0版本&#xff09;作为网络安全等级保护制度的最新标准&#x…

Revit 专业实用的BIM模型设计软件下载安装,Revit 最新版下载安装

Revit&#xff0c;该软件是专门为建筑信息模型&#xff08;BIM&#xff09;量身打造的&#xff0c;不仅极大提升了建筑设计师的工作效率&#xff0c;更为他们创造了一个更加精确、高效的设计环境。 在Revit的助力下&#xff0c;建筑设计师们能够轻松地进行建筑建模&#xff0c…

AI:开发者的助力还是终结者?

作为一名科技工作研发者&#xff0c;在科技浪潮汹涌澎湃的当下&#xff0c;AI 对于开发者的角色定位成为了一个备受瞩目的焦点话题。 AI 是在助力开发者&#xff0c;还是会取而代之&#xff1f;让我们从技术的角度深入剖析。 不可否认&#xff0c;AI 为开发者带来了前所未有的便…

Django QuerySet对象,all()方法

all()方法 在Django中&#xff0c;all()方法是QuerySet对象的一个方法&#xff0c;用于获取模型的所有实例。 当你调用ModelName.objects.all()时&#xff0c;Django会生成一个SQL查询&#xff0c;从数据库中获取该模型的所有记录&#xff0c;并返回一个QuerySet对象&#xf…

uniapp + vite中 uni.scss 使用 /deep/ 不生效(踩坑记录三)

vite 中使用 /deep/ 进行样式穿透报错 原因&#xff1a;vite 中不支持&#xff0c;换成 ::v-deep 或:deep即可

创建kset

1、kset介绍 2、相关结构体和api介绍 2.1 struct kset 2.2 kset_create_and_add kset_create_and_addkset_createkset_registerkobject_add_internalkobject_add_internal2.3 kset_unregister kset_unregisterkobject_delkobject_put3、实验操作 #include<linux/module.…

【MySQL8.0】 CentOS8.0下安装mysql报错权限问题的记录

这里写自定义目录标题 基本信息问题记录 基本信息 OS: Linux server-02 4.18.0-240.el8.x86_64 #1 SMP Fri Sep 25 19:48:47 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux MySQL: 8.0 问题记录 缺少类库 mysql: error while loading shared libraries: libncurses.so.5: cannot…

泛型 + 反射 + 注解 + 动态代理 + 设计模式 + Factory(BeanFactory,FactoryBean)

1.泛型 编译器可以对泛型参数进行检测&#xff0c;并且通过泛型参数可以指定传入的对象类型。比如 ArrayList<Person> persons new ArrayList<Person>() 这行代码就指明了该 ArrayList 对象只能传入 Person 对象&#xff0c;如果传入其他类型的对象就会报错。 原…

周周星分享7.3—基于气象大数据的自动站实况联合预测

赛题 2024中国高校计算机大赛 — 大数据挑战赛 经验分享 大家好&#xff0c;我是扫地僧团队的队长&#xff0c;以前参加这样打榜的比赛比较少&#xff0c;了解的打榜技巧不是太多&#xff0c;所以想从科研的角度给大家一点分享。 这次比赛主要从以下五个步骤进行&#xff1a…

全网最详细金融APP测试功能点-测试用例,详细整理(全)

2024软件测试面试刷题&#xff0c;这个小程序&#xff08;永久刷题&#xff09;&#xff0c;靠它快速找到工作了&#xff01;&#xff08;刷题APP的天花板&#xff09;-CSDN博客跳槽涨薪的朋友们有福了&#xff0c;今天给大家推荐一个软件测试面试的刷题小程序。https://blog.c…

660错题

不能局部求导,局部洛必达

IO多路复用学习

Linux中的I/O多路复用 相关基础概念 在学习I/O多路复用之前&#xff0c;先学习一些相关的基础概念&#xff0c;便于理解。 内核缓冲区和用户缓冲区 &#x1f62e; CPU 上会运行两种程序&#xff0c;一种是操作系统的内核程序&#xff08;也称为系统程序&#xff09;&#x…

[OC]萝卜圈Python手动游戏

小游戏示意图 游戏规则 1.wasd上下左右移动 2.玩家一次可以移动1-3随机距离&#xff0c;人机一次移动1格或斜着移 3.玩家需要躲避人机追杀 4.当出现如图所示情况时——你输了 5.墙&#xff08;概率通过&#xff0c;对人机无效&#xff09; 难度可根据代码自己调&#xff…

python - 列表 / 元组 / 字符串

一.列表 由于pyhon的变量没有数据类型&#xff0c;所以python是没有数组的&#xff08;因为数组只能存放一种类型&#xff0c;要么全部存放整型&#xff0c;要么全部存放浮点型&#xff09;&#xff0c;只有列表list&#xff0c;所以整数&#xff0c;浮点数&#xff0c;字符串…

机械设备制造企业MES系统解决方案介绍

机械设备制造行业涵盖了各类工业设备、工程机械、农业机械等多个领域&#xff0c;对生产精度、质量控制和效率提出了较高要求。为了提升生产效率、保证产品质量并满足客户需求&#xff0c;越来越多的机械设备制造企业引入了MES系统。本文将详细介绍MES系统在机械设备制造行业的…

【嵌入式DIY实例-ESP8266篇】-LCD ST7735显示网络时间

LCD ST7735显示网络时间 文章目录 LCD ST7735显示网络时间1、硬件准备2、代码实现本文将介绍如何使用 ESP8266 NodeMCU Wi-Fi 板实现互联网时钟,其中时间和日期显示在 ST7735 TFT 显示屏上。 ST7735 TFT是一款分辨率为128160像素的彩色显示屏,采用SPI协议与主控设备通信。 1…

Vue前端练习

此练习项目只涉及前端&#xff0c;主要是vue和ElementUI框架的使用。&#xff08;ElementUI官网&#xff1a;Element - The worlds most popular Vue UI framework&#xff09; 一、环境准备 安装idea 安装Node.js 一键式安装(不需要做任何配置) npm -v&#xff08;也可用nod…

封装stater时配置导入配置类提示功能

提示功能如下 使用注解导入配置属性时添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

前端初学java二(类、多态、接口、内部类、泛型)

目录 类 种类 Javabean类 测试类 工具类 类的初始化 构照函数 新建对象的内存图 static 继承 This Super 虚方法表 Override 修饰符权限 构造代码块 静态代码块 多态 前提 优点 缺点 示例 抽象方法 抽象类 接口 implements 继承 内部类 成员内部类…

windows@无密码的本地用户账户相关问题@仅用用户名免密登录远程桌面登录和控制@无密码用户访问共享文件夹以及挂载问题

文章目录 abstract此用户无法登录账户被禁用问题访问共享文件夹时带上凭据错误案例和解决 两类登录方式控制台登录与远程登录的区别为什么限制空密码账户只允许控制台登录相关安全策略如何修改该策略注意事项 启用允许被免密登录功能使用空密码进行远程桌面连接设置远程桌面链接…