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,就这样写。

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

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

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

相关文章

分布式(10)

目录 46.什么是Session Replication? 47.什么是Session数据集中存储&#xff1f; 48.什么是Cookie Based Session? 49.什么是JWT&#xff1f;使用JWT的流程&#xff1f;对比传统的会话有啥区别&#xff1f; 50.如何设计一个秒杀系统&#xff1f; 51.接口设计要考虑哪…

地址变量与函数进阶

指针与函数的高级用法 1.数组2.函数的重载3.函数的指针类型参数4.可变参数函数链表5.函数指针6.指针函数7.内联函数8.总结 在上节中我们简单谈论了指针变量&#xff0c;这节我们就来讨论指针变量的实际应用。 1.数组 相信有一定C语言基础的小伙伴一定很熟悉这个类型。数组可以…

Node.js(四)-express

1. 初识express 1.1 express简介 1.1.1 什么是express 官方&#xff1a;Express是基于Node.js平台&#xff0c;快速、开放、极简的web开发框架。 通俗&#xff1a;Express的作用和Node.js内置的http模块类似&#xff0c;是专门用来创建web服务器的。 express的本质&#xff1…

KNN 分类(选择最佳的 K 值,并可视化模型精度与 n_neighbors 的关系)

import matplotlib.pyplot as plt from sklearn.datasets import load_breast_cancer from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier# 导入乳腺癌数据集 cancer load_breast_cancer()# 划分训练集和测试集 X_tra…

函数作用域和块级作用域

(1)Es5之前的作用域 在Es5之前只有全局作用域和函数作用域。 (1)全局作用域 范围:在winodw全局里面都生效 例子: for(var i0;i<5;i){}console.log(window.ii); 返回的结果是:True (2)函数作用域 范围:在这个函数里面生效 例子: function fn(b) {console.log(b);}con…

如何配置Zabbix告警邮件通知并基于GPT提供解决方案?

一、概述 时间来到2023年末&#xff0c;距离Open AI发布GPT-3.5&#xff0c;首次向公众推出ChatGPT已经整整过去了一年。如今&#xff0c;以ChatGPT为代表的人工智能模型已然被应用众多领域&#xff0c;当然也包括IT运维。在IT运维中&#xff0c;通过对接运维监控平台&#xff…

类和对象之拜访对象村

类和对象 1.面向对象的初步认知 ————&#xff08;进入对象村&#xff09;1.1为什么称为对象村1.2面向对象和面向过程 2.类的定义和使用————&#xff08;这个陌生人是谁&#xff1f;&#xff09;2.1简单认识类2.2类的定义格式2.3定义一个狗类 3.类的实例化之new一个“对…

Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found

IDEA创建spring boot项目的时候&#xff0c;pom.xml 文件中spring-boot-maven-plugin报红。 解决方法&#xff1a; 给spring-boot-maven-plugin指定版本 原因&#xff1a; idea自动找的插件版本是其他版本的&#xff0c;和自己设置的不同&#xff0c;导致idea在本地maven仓库…

深入解析JMeter响应断言功能

JMeter 是一个功能强大的性能测试工具&#xff0c;它可以模拟大量用户并发访问网站或应用程序&#xff0c;以测试其性能和稳定性。在进行性能测试时&#xff0c;我们需要对响应结果进行断言&#xff0c;以确保应用程序或网站的功能和性能符合预期。 在 JMeter 中&#xff0c;响…

Spring之强大的DefaultListableBeanFactory

系列文章目录 如何查看类继承结构参考这里 文章目录 系列文章目录一、DefaultListableBeanFactory的类继承实现结构二、实现接口 一、DefaultListableBeanFactory的类继承实现结构 二、实现接口 AliasRegistry&#xff1a;支持别名功能&#xff0c;一个名字可以对应多个别名B…

SpringBoot整合sentinel

1、引入依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> 2、 配置文件添加 spring:cloud:sentinel:transport:dashboard: ip:8858 项目重启&#x…

[PyTorch][chapter 9][李宏毅深度学习][CNN]

前言&#xff1a; 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;是一种深度学习模型或类似于人工神经网络的多层感知器&#xff0c;常用来分析视觉图像。卷积神经网络的创始人是着名的计算机科学家Yann LeCun&#xff0c;目前在Facebook工作&#xff0c;…

Time-series forecasting with deep learning: a survey

人们开发了许多深度学习架构来适应不同领域的时间序列数据集的多样性。在本文中&#xff0c;我们调查了一步前进和多水平时间序列预测中使用的常见编码器和解码器设计&#xff0c;描述了如何将时间信息纳入每个模型的预测中。接下来&#xff0c;我们重点介绍混合深度学习模型的…

数据结构【排序篇】

数据结构【排序篇】 文章目录 数据结构【排序篇】前言为什么突然想学算法了&#xff1f;为什么选择码蹄集作为刷题软件&#xff1f; 目录一、插入排序二、交换排序三、 选择排序四、归并排序和基数排序 结语 前言 为什么突然想学算法了&#xff1f; > 用较为“官方”的语言讲…

SpringIOC之support模块DefaultMessageSourceResolvable

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

【ITK库学习】使用itk库进行图像配准:变换Transform(三)

目录 1、itkAffineTransform 仿射变换2、itkBSplineDeformableTransform B样条可变形变换 1、itkAffineTransform 仿射变换 该类实现向量空间的仿射变换&#xff08;例如空间坐标&#xff09; 此类允许定义和操作n维仿射空间&#xff08;及其关联的向量空间&#xff09;对其自…

QT C++调用python传递RGB图像和三维数组,并接受python返回值(图像)

目的&#xff1a; 用QT调用python代码&#xff0c;将QT读取的图像(Qimage)作为参数传入python中&#xff0c;将QT的三维数组作为参数传递给python&#xff0c;python接收QT传入的图像进行计算&#xff0c;将结果返回给QT并显示。 一 .pro 头文件的配置&#xff0c;和lib库的…

在 Mac 上轻松安装和配置 JMeter

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 要安装 Java&#xff0c;请按…

数字孪生与边缘计算的结合

数字孪生与边缘计算的结合可以在物理实体附近进行实时数据处理和决策&#xff0c;从而提高响应速度、降低延迟&#xff0c;并有效地利用边缘资源。以下是数字孪生在边缘计算中的一些应用&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开…

JavaWeb——后端之SpringBoot基础知识

2. SpringBoot 官网&#xff1a;https://spring.io/ Spring全家桶&#xff1a;Spring已经形成了一种开发生态圈&#xff0c;其提供的若干子项目分别用于完成特定的功能 Spring Boot简化了Spring Framework&#xff0c;不用底层实现那么配置繁琐&#xff0c;可以快速构建应用…