vue3 插槽 slot 使用

news2024/11/27 20:25:19

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.coloradmin.cn/o/1357089.html

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

相关文章

【uniapp】多规格选择

效果图 VUE <template> <view><view class"wp-80 pd-tb-40 mg-auto"><button type"warn" click"showDrawer(showRight)">筛选</button></view><!-- 筛选-uni-drawer --><uni-drawer ref"s…

tolist()读取Excel列数据,(Excel列数据去重后,重新保存到新的Excel里)

从Excel列数据去重后&#xff0c;重新保存到新的Excel里 import pandas as pd# 读取Excel文件 file r"D:\\pythonXangmu\\quchong\\quchong.xlsx" # 使用原始字符串以避免转义字符 df pd.read_excel(file, sheet_namenameSheet)# 删除重复值 df2 df.drop_duplica…

HTTP打怪升级之路

新手村 上个世纪80年代末&#xff0c;有一天&#xff0c;Tim Berners-Lee正在工作&#xff0c;他需要与另一台计算机上的同事共享一个文件。他尝试使用电子邮件&#xff0c;但发现电子邮件不能发送二进制文件。Tim Berners-Lee意识到&#xff0c;他需要一种新的协议来共享二进制…

IntelliJ IDEA 如何配置git

在 IntelliJ IDEA 中配置 Git 的步骤如下&#xff1a; 打开 IntelliJ IDEA。找到 File–>Setting–>Version Control–>Git–>Path to Git executable。在 Git 的安装路径下找到 cmd 文件夹下的 git.exe&#xff0c;到此 Git 配置已完成。

Windows 安装配置 Anaconda、CUDA、cuDNN、pytorch-cuda全流程

Windows 安装配置 Anaconda、CUDA、cuDNN、pytorch-cuda全流程 1. 安装Anaconda 网址&#xff1a;https://repo.anaconda.com/archive/ 选择第一个下载即可 双击exe文件&#xff0c;按安装向导安装即可&#xff08;除安装路径自己选择外&#xff0c;其余均可按默认选项&#x…

02 Deep learning algorithm

Neural Networks target&#xff1a; inference&#xff08;prediction&#xff09;training my own modelpractical advice for building machine learning systemdecision Tress application: speech&#xff08;语音识别&#xff09; ----> images(计算机视觉)—> t…

【Redis-09】Redis哨兵机制的实现原理-Sentinel

Sentinel是Redis高可用性的解决方案&#xff1a;由一个或者多个Sentinel实例组成的哨兵系统监视多个主从服务器&#xff0c;并实现主从服务器的故障转移。 Sentinel本质上只是一个运行在特殊模式下的Redis服务器&#xff0c;使用以下命令可以启动并初始化一个Sentinel实例&…

面试题:聊聊 SpringBoot 中的 SPI 机制

文章目录 简介Java SPI实现示例说明实现类1实现类2相关测试 源码分析Spring SPISpring 示例定义接口相关实现 相关测试类输出结果源码分析 总结 简介 SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制&#xff0c;可以用来启用框架扩展和替换组件,主要用于框架…

灸哥问答:数据结构对软件开发的作用

在软件开发的浩瀚海洋中&#xff0c;数据结构如同一座坚固的灯塔&#xff0c;为开发者指明方向&#xff0c;确保他们在构建复杂系统时不会迷失。数据结构不仅仅是编程的基础&#xff0c;更是高效、稳定、可扩展软件的核心。 一、提升算法效率 数据结构与算法紧密相连&#xf…

linux 使用iniparser读取.ini文件的配置信息

为什么要用项目配置文件 对于很多程序中要用的参数如果是可变的&#xff0c;那么最好的处理方式就是通过main(int argc,char **argv) 函数参数传递&#xff0c;或者从别的地方去获取&#xff0c;这其中之一就是配置文件&#xff0c;但是在一个成熟和架构完善的系统&#xff0c…

Spring之强大的DefaultListableBeanFactory

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

Leetcode2962. 统计最大元素出现至少 K 次的子数组

Every day a Leetcode 题目来源&#xff1a;2962. 统计最大元素出现至少 K 次的子数组 解法1&#xff1a;滑动窗口 算法如下&#xff1a; 设 mx max⁡(nums)。右端点 right 从左到右遍历 nums。遍历到元素 xnums[right] 时&#xff0c;如果 xmx&#xff0c;就把计数器 co…

qt源码阅读准备

qt源码阅读准备 阅读qt源码前先了解以下知识&#xff0c;对阅读qt源码有极大的好处。 D-pointer介绍 D-pointer介绍 d-pointer它可以把一个类库的实施细节对使用的用户隐藏&#xff0c; 而且对实施的更改不会打破二进制兼容。其基本贯穿qt所有类。 Qt类的的结构 我们以QO…

【unity】基于Obi的绳/杆蓝图、绳杆区别及其创建方法

绳索 是通过使用距离和弯曲约束将粒子连接起来而形成的。由于规则粒子没有方向(只有位置)&#xff0c;因此无法模拟扭转效应(维基百科)&#xff0c;绳子也无法保持其静止形状。然而&#xff0c;与杆不同的是&#xff0c;绳索可以被撕裂/劈开&#xff0c;并且可以在运行时改变其…

第3章 【例题】(完整版)

目录 前言 【例3.1】有关成绩结构体的例子 【例3.2】使用Score类的完整程序 【例 3.3】一个存在错误的程序 【例3.4】用对象赋值语句的例子 【例3.5】为类Score定义一个构造函数 【例3.6】建立对象的同时&#xff0c;用构造函数给数据成员赋初值 【例3.7】用成员初始…

智能手机2024:狂卷“微创新”后如何突破新机遇

文 | 智能相对论 作者 | 楷楷 2023年&#xff0c;智能手机市场终于开始展露曙光。Counterpoint Research数据显示&#xff0c;2023年10月全球智能手机销量同比增长5%&#xff0c;智能手机市场出货量在经历了连续27个月的同比下滑后&#xff0c;首次出现同比正增长。 特别是在…

IDEA卡在”正在解析Maven依赖项“的解决方法

修改Maven镜像&#xff0c;修改Maven镜像为阿里云镜像 1.文件路径 C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\plugins 2.因为我使用的是InteliJ idea 自带的Maven&#xff0c;所以直接去idea 插件安装目录&#xff0c;找到Maven插件&#xff0c;找到setting.xml 文…

Linux第4步_安装VMwareTools

安装Ubuntu操作系统后&#xff0c;就可以安装VMwareTools了&#xff0c;目的是实现“电脑和虚拟机之间互相复制粘贴文件”。 1、双击桌面图标“VMware Workstation Pro”&#xff0c;然后点击下图中的“开机”&#xff0c;打开虚拟机电源。 2、双击下图中的用户名“zgq” 3、…

Ubuntu上使用node搭建本地静态http服务器

1.搭建步骤 1.安装Node.js。首先确保你的Ubuntu系统已经安装了Node.js。如果没有安装&#xff0c;可以通过以下命令进行安装&#xff1a; sudo apt-get update sudo apt-get install nodejs #安装nodejs 2.安装npm。npm是Node.js的包管理器&#xff0c;一般会随着Node.js一…

面试算法90:环形房屋偷盗

题目 一条环形街道上有若干房屋。输入一个数组表示该条街道上的房屋内财产的数量。如果这条街道上相邻的两幢房屋被盗就会自动触发报警系统。请计算小偷在这条街道上最多能偷取的财产的数量。例如&#xff0c;街道上5家的财产用数组[2&#xff0c;3&#xff0c;4&#xff0c;5…