vue3 插槽 slot 使用

vue3 插槽 slot 使用

在 Vue3 中,插槽(slot)是一种重要的组件复用和内容分发机制。通过使用插槽,可以让组件更加灵活和具有可复用性,在不同的地方渲染不同的内容,同时保证相同的样式。

插槽资料

官网介绍:https://cn.vuejs.org/guide/components/slots

插槽的作用域

由于插槽内容本身是在父组件中定义的,所以可以访问到父组件的数据作用域,但是无法访问到子组件的数据作用域。这是因为Vue表达式的词法作用域规则和JavaScript一样,只能访问其定义时所处的作用域。用官方文档的话来说,父组件模版中的表达式只能访问父组件的作用域;子组件模版中的表达式只能访问子组件的作用域。

插槽的基本使用

插槽的基本使用很简单,他类似于一个插排,插槽就是一个一个的口,可以随意的插东西进去。

比如说现在我写了一个 slotModel.vue 组件:

<template><div><p style="color: green;">我是插槽组件</p><slot></slot></div>
</template><script setup lang="ts"></script><style scoped></style>

其中 <slot></slot> 标签就是插槽。

父组件使用这个子组件:

<template><p class="ed-p">我是ed. vue3 插槽</p><slotModel></slotModel>
</template>
<script setup lang="ts">
import slotModel from './slotModel.vue';</script>
<style scoped>
.ed-p {margin: 20px;color: hotpink;font-size: 20px;font-weight: 550;
}
</style>

我们看一下效果:

在这里插入图片描述

看,像普通组件一样可以加载显示出来。

但是我们改一下,在引用组件的时候,我们传递一个数据进去:

<slotModel>你好,我是ed.</slotModel>

然后我们发现,数据显示出来了:

在这里插入图片描述

这里我们传进去的数据,会在插槽组件的 <slot></slot> 标签处作为内容进行显示,这!就是插槽!!

OK,插槽除了可以展示基本的文本信息外,还可以插入标签。

比如我们插入一个按钮进去:

<template><p class="ed-p">我是ed. vue3 插槽</p><slotModel><button>按钮</button></slotModel>
</template>

然后页面就会变成插入的按钮:

在这里插入图片描述

好的,这是最基本的使用。

再说一嘴,我们在父组件插入的是:

<slotModel><button>按钮</button>
</slotModel>

他会把插槽组件的 <slot></slot> 部分替换成 <button>按钮</button> ,如果插槽组件有多个 <slot></slot> 的话,会同时替换,比如:

<template><div><p style="color: green;">我是插槽组件</p><slot></slot><slot></slot><slot></slot></div>
</template>

现在插槽组件有三个口,那么这三个口都被被 <button>按钮</button> 给替换掉:

在这里插入图片描述

看,都替换了吧!好的,就这样。

插槽的默认内容

看上面的案例,我们在插槽的部分渲染了按钮,因为我们父组件传进去的就是按钮,所以可以正常渲染,那么问题来了,如果我不传,我会显示啥!我们试一下,首先我们修改一下插槽组件,只留一个口:

<template><div><p style="color: green;">我是插槽组件</p><slot></slot></div>
</template>

然后我们父组件使用插槽的时候,我们不传东西进去:

<template><p class="ed-p">我是ed. vue3 插槽</p><slotModel><!-- 不传东西 --></slotModel>
</template>

我们不传的话:

在这里插入图片描述

插口部分直接就是空了,没有东西渲染出来。那么我想在没有数据传进来得时候,插口默认一个数据,比如默认显示“暂无数据”四个字怎么办?

so easy!只需要在插口上写上就可以了:

<template><div><p style="color: green;">我是插槽组件</p><slot>暂无数据</slot></div>
</template>

这个 <slot></slot> 是用来替换父组件传进来得内容的,简单理解成占位符哈,不恰到,先这样理解。如果没有传肯定是空,但是我们在插口上添加了自己的内容,就像案例上面的 <slot>暂无数据</slot> 一样,这个时候:如果父组件传递了内容进来,则还是和之前一样替换掉<slot></slot> ,如果没有传递,则默认展示<slot></slot> 中的内容,所以这样的话,在父组件不传递内容进来的时候,就会显示 “暂无数据” 四个字了:

在这里插入图片描述

看默认数据显示出来了, 当然我案例用的文本,其实标签啥的都是可以的哈,我就不写了,自己试一下就可以了!

具名插槽

具名插槽的意思就是带有名字的插槽,什么时候用呢,打个比方哈,就譬如说:我一个组件里面有插槽,但是我可能有好几个插口,我想分别用来显示不同的内容,比如下面的内容哈:

<template><div style="background-color: green;padding:20px;color:#fff"><!-- 插口一 --><slot></slot></div><div style="background-color: red;padding:20px;color:#fff"><!-- 插口二 --><slot></slot></div><div style="background-color: yellow;padding:20px;color:#fff"><!-- 插口三 --><slot></slot></div></template>

上面代码,我这一个组件有三个插口,如果我们父组件传进来一个内容看一下效果:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><button>按钮</button></slotModel></template>

我们在父组件,往插口组件传进一个按钮,会有什么效果?上面说了一遍了其实,同时替换:

在这里插入图片描述

看,三个插口都被替换了。

假设我现在想让 插口一显示“插口一”按钮,插口二显示“插口二”按钮,插口三显示“插口三”按钮,怎么办?这个时候就需要用到具名插槽了,我们给每一个插口设置一个名字,然后父组件传内容的时候,根据名字来确定放在哪个插口里面。

比如我们先给插口起一个名字:

<template><div style="background-color: green;padding:20px;color:#fff"><!-- 插口一 --><slot name="one"></slot></div><div style="background-color: red;padding:20px;color:#fff"><!-- 插口二 --><slot name="two"></slot></div><div style="background-color: yellow;padding:20px;color:#fff"><!-- 插口三 --><slot name="three"></slot></div>
</template>

我们给每个插槽起了一个名字,然后我们父组件就可以根据名字设置具体是给哪个插槽传递的内容 :

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><template v-slot:one><button>插口一</button></template><template v-slot:two><button>插口二</button></template><template v-slot:three><button>插口三</button></template></slotModel>
</template>

template 标签啥作用我就不说了哈,学 vue 的都知道,他只是作为容器包裹一下,不会实际渲染出来。只需要知道,要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令,我们主要看 v-slot:one,我们通过 v-slot: + 插槽名 的方式来标明该部分的内容通过哪个插槽来渲染,即渲染到哪个插槽。看渲染结果:

在这里插入图片描述

看,完全没有问题!

其实这个 v-slot: + 插槽名 还有一个简写的方式,就是 # + 插槽名,效果是一样的,比如说插口一:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><template #one><button>插口一</button></template><template v-slot:two><button>插口二</button></template><template v-slot:three><button>插口三</button></template></slotModel>
</template>

我们可以看一下,效果是完全一样的:

在这里插入图片描述
总结一下:v-slot 有对应的简写 #,因此 <template v-slot:one> 可以简写为 <template #one>。其意思就是“将这部分模板片段传入子组件的 one 插槽中”

有一点需要特别说一下,你看我们在插槽组件里面都给插槽设置了名字,那我如果在父组件使用的时候,不使用 v-slot: + 插槽名 设置渲染到哪个插槽里面会出现什么情况?

看下面父组件的代码:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><button>插口一</button><template v-slot:two><button>插口二</button></template><template v-slot:three><button>插口三</button></template></slotModel>
</template>

看上面代码,我在插口一的那部分,没有说设置给哪个插槽渲染,这时候会出什么问题?

在这里插入图片描述

看结果,直接不显示了,因为没有插槽能渲染他。

那我就想渲染一个没有设置插槽名字的内容怎么办?其实很简单,写一个不就完事了:

<template><div style="background-color: green;padding:20px;color:#fff"><!-- 插口一 --><slot name="one"></slot></div><div style="background-color: red;padding:20px;color:#fff"><!-- 插口二 --><slot name="two"></slot></div><div style="background-color: yellow;padding:20px;color:#fff"><!-- 插口三 --><slot name="three"></slot></div><div style="background-color: blue;padding:20px;color:#fff"><!-- 插口四 --><slot></slot></div>
</template>

看代码,我们增加了一个插口四,没有设置插口的名字,这时候,父组件没设置名字的内容就会在这里显示:

在这里插入图片描述

所以说:这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 <slot> 出口会隐式地命名为“default”。

所以 <slot></slot><slot name="default"></slot> 是一样的。

渲染作用域

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

比如说下面的例子。

首先我们插槽组件只留一个插槽:

<template><div style="background-color: green;padding:20px;color:#fff"><slot></slot></div>
</template>

然后我们在父组件定义一个变量:

const msg = ref("你好,我是ed.")

然后我们在父组件插槽内容里面使用一下这个变量:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><button>{{ msg }}</button></slotModel>
</template>

能不能正常显示?理论上这个<button>{{ msg }}</button> 是要传进子组件,然后子组件把 <slot></slot> 替换成父组件传进来的 <button>{{ msg }}</button>,那么这个 msg 变量可以正常显示不?我们看一下效果:

在这里插入图片描述

OK。可以显示!所以:插槽内容可以访问到父组件的数据作用域,插槽内容无法访问子组件的数据。也就是说 Vue 模板中的表达式只能访问其定义时所处的作用域。

再来!

给这个按钮添加一个点击事件,然后在父组件和子组件都写他的回调,请问他会走谁的?

父组件:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel><button @click="btnClick">{{ msg }}</button></slotModel>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import slotModel from './slotModel.vue';const msg = ref("你好,我是ed.")const btnClick = () => {console.log("父组件  --- btnClick");
}</script>
<style scoped>
.ed-p {margin: 20px;color: hotpink;font-size: 20px;font-weight: 550;
}
</style>

子组件:

<template><div style="background-color: green;padding:20px;color:#fff"><slot></slot></div>
</template><script setup lang="ts">const btnClick = () => {console.log("子组件  --- btnClick");
}</script><style scoped></style>

然后我们看一下效果:

在这里插入图片描述

我们看到,点击之后打印的是父组件的。

作用域插槽

通过上面一部分我们已经知道了:插槽内容可以访问到父组件的数据作用域,插槽内容无法访问子组件的数据。

那么我就是矫情!我非得要插槽内容无法使用子组件的数据怎么办呢?

就是这一节需要用到的内容了,啊哈哈哈哈,作用域插槽!

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

看下面代码,我们在插槽组件定义两个变量:

const name = ref('我是ed.');
const age = ref(25);

然后咱们在 <slot></slot> 插槽里面,可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes:

<slot :myName="name" :age="age"></slot>

注意,我用的是 myName, 为啥不用 name 呢?因为是定义插槽名称的关键字,避免冲突换了一个哈!!好了,插槽把数据抛出去了,父组件可以直接用了:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel v-slot="slotProps"><button @click="btnClick">{{ slotProps.myName }} {{ slotProps.age }}</button></slotModel>
</template>

好的,看在引入的插槽组件上首先使用 v-slot="slotProps" 接收插槽组件的数量,其实 slotProps 他是一个对象,内容是 {myName: "我是ed.", age:25},然后我们在插槽内容就可以使用这个数据了:

在这里插入图片描述

完美~

当然如果愿意的话,结构也可以:

<template><p class="ed-p">我是ed. vue3 插槽</p><!-- 调用插槽组件 --><slotModel v-slot="{myName, age}"><button @click="btnClick">{{ myName }} {{ age }}</button></slotModel>
</template>

效果是一样的:

在这里插入图片描述

但是! 注意一点,这是默认插槽 的使用方式!具名插槽 的使用方式有一些小区别。

简单写哈,写够了:

    <template #two="twoProps"><button>{{twoProps.myName}}</button></template>

ok,就这样写。

好了好了,终于结束了,今天就到这里吧,然后其他内容可以去我博文最开始提供的官网地址去看,好了,结束了,拜拜!!

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

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

相关文章

freertos——任务通知知识总结与任务通知模拟及信号量实验、消息邮箱实验、事件标志组实验

1.任务通知概念 任务通知&#xff1a;用来通知任务的&#xff0c;任务控制块中的结构体成员变量 ulNotifiedValue就是这个通知值&#xff0c;不需要另外创建一个结构体可以直接接受别人发过来的通知 2.任务通知的优势及劣势 任务通知的优势&#xff1a; 效率更高 &#xff…

Android开发中“真正”的仓库模式

原文地址&#xff1a;https://proandroiddev.com/the-real-repository-pattern-in-android-efba8662b754原文发表日期&#xff1a;2019.9.5作者&#xff1a;Denis Brandi翻译&#xff1a;tommwq翻译日期&#xff1a;2024.1.3 Figure 1: 仓库模式 多年来我见过很多仓库模式的实…

Vue 单文件组件的基础入门指南

本文是我2年前做的一个学习小demo&#xff0c;在这里分享一下 希望对想要学习Vue的小伙伴能有一丢丢的小帮助~_~ 1 Vue CLI Vue CLI (opens new window)是一个基于Vue.js进行快速开发的完整系统。 这里我使用 Vue CLI 生成了一个Vue项目&#xff0c;命令为&#xff1a;vue cr…

C语言中指针变量如何使用

一、指针变量的定义与声明 1.1 定义 指针变量是用来存储另一个变量的内存地址的变量。在C语言中&#xff0c;指针变量的类型是指向某个类型的指针。例如&#xff0c;int *p; 表示一个整型指针变量p。 1.2 声明 指针变量的声明分为两种形式&#xff0c;一种是直接声明&#…

字节跳动 Spark 支持万卡模型推理实践

摘要&#xff1a;本文整理自字节跳动基础架构工程师刘畅和字节跳动机器学习系统工程师张永强在本次 CommunityOverCode Asia 2023 中的《字节跳动 Spark 支持万卡模型推理实践》主题演讲。 背景介绍 在云原生化的发展过程中 Kubernetes 由于其强大的生态构建能力和影响力&…

多线程基础入门【Linux之旅】——下篇【死锁,条件变量,生产消费者模型,信号量】

目录 一&#xff0c;死锁 1. 死锁的必要条件 2&#xff0c;避免死锁 二&#xff0c;条件变量 同步概念与竞态条件 条件变量——初始化 静态初始化 动态初始化 pthread_cond_destroy (销毁) pthread_cond_wait (等待条件满足) pthread_cond_signal (唤醒线程) ph…

2023 北京国炬软件年度总结—JeecgBoot与敲敲云

2023年对于北京国炬软件公司来说是一个充满成就和创新的一年。 我们成功推出了APass零代码平台—敲敲云&#xff0c;一款能够在5分钟内搭建应用的新一代零代码平台。自2023年1月1号正式上线以来&#xff0c;敲敲云已经突破了10万注册用户&#xff0c;并与数百家战略合作伙伴达…

Rust使用gRPC

需要先安装protoc&#xff08;Protocol Buffers Compiler&#xff09;&#xff0c;可据此Protobuf Compiler Installation下载 第一步&#xff1a;创建项目 创建两个新的Rust项目&#xff0c;分别作为服务端与客户端&#xff1a; cargo new rust_grpc_servercargo new rust_grp…

【python测验】数字游戏 取模数 数位dp

这题目看得人感觉要失去梦想…… 题目&#xff1a; 看不懂也做不出来&#xff0c;python方法未知&#xff0c;记录几个可供参考的帖子。 LightOJ 1068 Investigation 算法提高篇–动态规划&#xff08;八&#xff09;&#xff1a;数位DP&#xff08;3&#xff09;

【软件测试】2024年准备中/高级测试岗技术面试...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、软件测试基础知…

两阶段提交协议三阶段提交协议

两阶段提交协议 分布式事务是指会涉及到操作多个数据库的事务,在分布式系统中&#xff0c;各个节点之间在物理上相互独立&#xff0c;通过网络进行沟通和协调。 XA 就是 X/Open DTP 定义的交易中间件与数据库之间的接口规范&#xff08;即接口函数&#xff09;&#xff0c;交易…

Spring——Spring基于注解的IOC配置

基于注解的IOC配置 学习基于注解的IOC配置&#xff0c;大家脑海里首先得有一个认知&#xff0c;即注解配置和xml配置要实现的功能都是一样的&#xff0c;都是要降低程序间的耦合。只是配置的形式不一样。 1.创建工程 1.1 pom.xml <?xml version"1.0" encoding…