Vue之插槽(slot)

插槽是vue中的一个非常强大且灵活的功能,在写组件时,可以为组件的使用者预留一些可以自定义内容的占位符。通过插槽,可以极大提高组件的客服用和灵活性。

插槽大体可以分为三类:默认插槽,具名插槽和作用域插槽。

下面将一一介绍。

①默认插槽

这种插槽没有指定名称,用于接受父组件传递的未明确指定插槽名称的内容。在子组件中使用<slot></slot>定义插槽所在位置,父组件在书写子组件的标签体里书写插入到该插槽的内容。

代码如下:

父组件:index.vue

<!--
 * @Author: RealRoad
 * @Date: 2024-10-18 10:49:28
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-11-14 14:13:02
 * @Description: 
 * @FilePath: \project_10_08\vite-project\src\views\home\index.vue
-->

<template>
 <div class="box">
  <Category class="content">
    <div>我是文本</div>
    <img src="https://img0.baidu.com/it/u=454995986,3330485591&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375" alt="">
  </Category>
  <Category class="content">
    <el-button type="primary" size="default" @click="">一个按钮</el-button>
    
  </Category>
  <Category class="content">
    <el-card shadow="always" :body-style="{ padding: '20px' }">
      <div slot="header">
        <span>卡片标题</span>
      </div>
      <!-- card body -->
       <div>
        卡片体
       </div>
    </el-card>
    
  </Category>
 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'
import Category from './Category.vue'
</script>

<style scoped lang="scss">
.box{
  display:flex;
  justify-content: space-evenly;
  margin-top: 20px;
  .content{
    margin-left: 10px;
    background:pink;
    text-align: center;
    width: 400px;
    height: 600px;
    img{
      width: 100%;
    }
  }
}
</style>

子组件:Category.vue

<template>
 <div>
  我是子组件
  <!-- 一个默认插槽 -->
  <slot>插槽的默认内容</slot>
 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'

</script>

<style scoped>

</style>

来看效果:

当然了,在子组件中,可以书写插槽的默认内容,就是说如果父组件没有书写任何内容,就会默认使用子组件插槽内的内容。

 再写一个子组件,看一下效果

②具名插槽

顾名思义,就是带有名称的插槽,用于接受父组件中明确指定插槽名称的内容。

这里需要注意,vue2和vue3的写法略有不同,因为v3兼容v2,所有有些老版本的项目写的插槽还是v2的写法。

首先看v3的具名插槽写法:

子组件的写法相同,在子组件中使用<slot name="插槽名"></slot>就可以给插槽起一个名字。

子组件(NamedSlot.vue):

<template>
 <div>
  我是子组件2
  <!-- 一个默认插槽 -->
  <slot name="top">插槽的默认内容</slot>
  <slot name="bottom">插槽的默认内容</slot>
 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'

</script>

<style scoped>

</style>

来到父组件(index.vue):v3

<!--
 * @Author: RealRoad
 * @Date: 2024-10-18 10:49:28
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-11-14 14:40:49
 * @FilePath: \project_10_08\vite-project\src\views\home\index.vue
 * @Description: 
-->

<template>
 <div class="box">
  <NamedSlot class="content">
    <template #top>
    <div >我是文本</div>
  </template>
  <template #bottom>
      <img src="https://img0.baidu.com/it/u=454995986,3330485591&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375" alt="">

    </template>
  </NamedSlot>
  <Category class="content">
    <el-button type="primary" size="default" @click="">一个按钮</el-button>
    
  </Category>
  <Category class="content">
    <el-card shadow="always" :body-style="{ padding: '20px' }">
      <div slot="header">
        <span>卡片标题</span>
      </div>
      <!-- card body -->
       <div>
        卡片体
       </div>
    </el-card>
    
  </Category>
  <Category class="content"></Category>
 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'
import Category from './Category.vue'
import NamedSlot from './NamedSlot.vue';
</script>

<style scoped lang="scss">
.box{
  display:flex;
  justify-content: space-evenly;
  margin-top: 20px;
  .content{
    margin-left: 10px;
    background:pink;
    text-align: center;
    width: 400px;
    height: 600px;
    img{
      width: 100%;
    }
  }
}
</style>

可以对比一下上面的默认插槽,我们只修改了第一个子组件,其他的还是保持不变。

先看一下效果:

效果是一样的,不过是我们在子组件中起了名字,这样我们就可以在父组件随便改变顺序,就不用改变代码顺序了,直接修改插槽的名字即可。

说一下v3中的父组件的具名插槽的写法:

<子组件名称 >

    <template #插槽名>

        插槽内容

    </template>

</子组件名称> 

这样的格式,借用了template标签,并在标签上使用#的简写形式,也是现在element-plus等新版UI组件库使用的方式。

说完了v3,那一定要说一下老版本的v2写法,毕竟老项目中的都是这样的写法:

<子组件名称>

<子组件内容--标签 slot="插槽名"> </子组件内容--标签 >

</子组件名称>

注意:这里面在测试的时候出现了一个误区,我直接卸载了子组件名称的属性上,导致里面的内容也是无法正常显示。

这就比较难受,在vue3项目中使用vue2的老具名插槽用法不显示,原因可能有很多,保险起见,还是专门用脚手架建立的vue2项目中进行测试。

 所以紧急来到上次做的vue2项目中,进行老语法测试:

父组件:index.vue

<!--
 * @Author: RealRoad
 * @Date: 2024-11-12 09:25:23
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-11-14 15:29:28
 * @Description: 
 * @FilePath: \datalized-crm-ui\datalized-crm-ui\src\views\test\index.vue
-->
<!--
 * @Author: RealRoad
 * @Date: 2024-11-12 09:25:23
 * @LastEditors: Do not edit
 * @LastEditTime: 2024-11-12 16:10:43
 * @Description: 
 * @FilePath: \datalized-crm-ui\datalized-crm-ui\src\views\test\index.vue
-->
<template>
    <div>
        <ComponentA ><div slot="top">测试一波具名插槽
          <img src="https://img1.baidu.com/it/u=1047145501,4073770646&fm=253&app=120&size=w931&n=0&f=JPEG&fmt=auto?sec=1731690000&t=14c402c69d53274bb7fa9af0d0e0e392" alt="">
        </div></ComponentA>
        <ComponentB />
        <!-- <a-form layout="inline" class="my-customer-form" @keyup.enter.native="searchQuery">
            <a-form-item label="商机名称">
              <a-input
                placeholder="请输入商机名称"
                
              >
              </a-input>
            </a-form-item>
            <a-form-item label="客户名称">
              <a-input
                placeholder="请输入客户名称"
                allowClear
               
              >
              </a-input>
            </a-form-item>
            
            <a-form-item label="赢单率">
              <a-select
                :getPopupContainer="node => node.parentNode"
                placeholder="请选择赢单率"
                default-value="10%"
                style="width: 100%"
                
                :style="{ width: searchItemWidth }"
              >
                <a-select-option value="10%"> 10%</a-select-option>
                <a-select-option value="20%"> 20%</a-select-option>
                <a-select-option value="30%"> 30%</a-select-option>
                <a-select-option value="40%"> 40%</a-select-option>
                <a-select-option value="50%"> 50%</a-select-option>
                <a-select-option value="60%"> 60%</a-select-option>
                <a-select-option value="70%"> 70%</a-select-option>
                <a-select-option value="80%"> 80%</a-select-option>
                <a-select-option value="90%"> 90%</a-select-option>
                <a-select-option value="100%"> 100%</a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="商机状态">
              <j-dict-select-tag
                type="radioButton"
                
                
                dictCode="chance_status"
                
              />
            </a-form-item>
            
          </a-form>
          <hr>
          展示一下过度
          <div>
            <a-button type="primary" @click="isShow=!isShow">显示/隐藏</a-button>
            <transition name="mez" appear @afterEnter="handleEnter"
            @after-leave="handleLeave"
            @appear="handleAppear"
            @after-appear="myhandleEnter"
            @before-enter="myEnter"
            @enter="handleEnter"
            
            @leave="handleLeave">
            
                <h1 v-show="isShow" >测试文本</h1>
            </transition>
          </div>1112 -->
    </div>
</template>

<script>

import ComponentA from './brotherA.vue'
import ComponentB from './brotherB.vue'
import JDictSelectTag from '@/components/dict/JDictSelectTag'
export default {
    name: 'Test',
    data() {
        return {
            searchItemWidth:'200px',
            isShow:true
        };
    },
    methods: {
        handleEnter(){
            console.log('after-enter');
        },
        handleLeave(){
            console.log('after-leave');
        },
        handleAppear(){
            console.log('appear');
        },
        handleEnter(){
            console.log('enter');
        },
        handleLeave(){
            console.log('leave');
        },
        myEnter(){
            console.log('before-enter');
        },
        myhandleEnter(){
            console.log('after-appear');
        },

    },
    components: {
        ComponentA,
        ComponentB
    },

}
</script>

<style lang="less" scoped>
// @import '~@assets/less/common.less';

h1{
    background-color: rgb(98, 57, 133);
    
}
//进入的起点
.mez-enter,.mez-leave-to{
    transform: translateX(-100%);
}
//进入的过程
.mez-enter-active,.mez-leave-active{
    // animation: identifier 1s linear;
    transition: 0.5s linear;
}
// .mez-leave-active{
//     // animation: identifier 1s linear reverse;
// }
//进入的终点
.mez-enter-to,.mez-leave{
    transform: translateX(0);
}
//离开的起点
// .mez-leave{
//     transform: translateX(0);
// }
// //离开的终点
// .mez-leave-to{
//     transform: translateX(-100%);
// }


// @keyframes identifier {
//     from{
//         transform: translateX(-100%);
//     }
//     to{
//         transform: translateX(0px);
//     }
// }
</style>

子组件brotherA.vue:

template>
<div>
 兄弟A组件
 <!-- <a-button type="primary" size="default" @click="handleClick">点我给B兄弟传值</a-button> -->

 <slot name="top">如果父组件没有内容显示我</slot>
</div>
</template>

<script>
export default {
 name: '',
 data() {
  return {
   
  };
 },
 methods: {
    // handleClick() {
    //   this.$emit('sendValue', '兄弟A组件传给B的参数');
    // }
  
 }
}
</script>

<style scoped>

</style>

来看效果:

果然和脚手架有关,可以正常使用。在vue3项目中哪怕是写成了不是setup语法糖的写法,也是不能正常显示,这里兄弟们需要注意一下,也有可能是我用vite建立的是vue3的项目,因为既有vue3的setup语法糖写法,又有vue2的export default{}写法,造成的冲突。【另外,这里还有一个vue2.7还是啥来着提出的配合template的<template v-slot:插槽名></template>的简写写法,这个就不展开说了,知道就行。】

③作用域插槽

 它是一种特殊的插槽,允许子组件爱你将数据暴露给父组件的插槽内容。在子组件中,语法为<slot :数据名=“数据值”></slot>的写法将自己的数据传递给插槽。

而在父组件中,通过<template v-slot:插槽名称=“slotProps”>接受数据,并使用slotProps来访问传递过来的数据。

子组件:

<template>
  <div>
    <slot :users="userList"></slot>
  </div>
</template>

<script setup>
import { reactive } from 'vue';

// 定义一个响应式数组,作为作用域插槽的数据源
const userList = reactive([
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 }
]);
</script>

<style scoped>
/* 子组件的样式(如果需要的话) */
</style>

父组件:

<template>
  <div>
    <h1>作用域插槽示例</h1>
    <ChildComponent>
      <!-- 使用 v-slot 接收作用域插槽的数据 -->
      <template #default="{ users }">
        <ul>
          <li v-for="user in users" :key="user.name">
            {{ user.name }} - {{ user.age }}
          </li>
        </ul>
      </template>
    </ChildComponent>
  </div>
</template>

<script setup>
import ChildComponent from './ChildComponent.vue';
</script>

<style scoped>
/* 父组件的样式(如果需要的话) */
</style>

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

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

相关文章

从零开始深度学习:全连接层、损失函数与梯度下降的详尽指南

引言 在深度学习的领域&#xff0c;全连接层、损失函数与梯度下降是三块重要的基石。如果你正在踏上深度学习的旅程&#xff0c;理解它们是迈向成功的第一步。这篇文章将从概念到代码、从基础到进阶&#xff0c;详细剖析这三个主题&#xff0c;帮助你从小白成长为能够解决实际…

Python 绘图工具详解:使用 Matplotlib、Seaborn 和 Pyecharts 绘制散点图

目录 数据可视化1.使用 matplotlib 库matplotlib 库 2 .使用 seaborn 库seaborn 库 3 .使用 pyecharts库pyecharts库 注意1. 确保安装了所有必要的库2. 检查Jupyter Notebook的版本3. 使用render()方法保存为HTML文件4. 使用IFrame在Notebook中显示HTML文件5. 检查是否有其他输…

【C++】vector 类模拟实现:探索动态数组的奥秘

&#x1f31f; 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。&#x1f31f; 如果你对string&#xff0c;vector还存在疑惑&#xff0c;欢迎阅读我之前的作品 &#xff1a; 之前文章&#x1f525;&#x1f52…

【ubuntu18.04】vm虚拟机复制粘贴键不能用-最后无奈换版本

我是ubuntu16版本的 之前费老大劲安装的vmware tools结果不能用 我又卸载掉&#xff0c;安装了open-vm-tools 首先删除VMware tools sudo vmware-uninstall-tools.pl sudo rm -rf /usr/lib/vmware-tools sudo apt-get autoremove open-vm-tools --purge再下载open-vm-tools s…

使用原生 OpenTelemetry 解锁各种可能性:优先考虑可靠性,而不是专有限制

作者&#xff1a;来自 Elastic Bahubali Shetti•Miguel Luna Elastic 现在支持使用 OTel Operator 在 Kubernetes 上部署和管理 Elastic Distributions of OpenTelemetry (EDOT)。SRE 现在可以访问开箱即用的配置和仪表板&#xff0c;这些配置和仪表板旨在通过 Elastic Observ…

【freertos】FreeRTOS信号量的介绍及使用

FreeRTOS信号量 一、概述二、PV原语三、函数接口1.创建一个计数信号量2.删除一个信号量3.信号量释放4.在中断释放信号量5.获取一个信号量&#xff0c;可以是二值信号量、计数信号量、互斥量。6.在中断获取一个信号量&#xff0c;可以是二值信号量、计数信号量7.创建一个二值信号…

【生物服务器】数据分析//论文润色/组学技术服务 、表观组分析、互作组分析、遗传转化实验、生物医学

DNA亲和纯化测序&#xff08;DAP-seq&#xff09;和组蛋白甲基化修饰是表观遗传学研究中两个重要的技术手段&#xff0c;它们在揭示基因表达调控机制和染色质结构动态变化中发挥着关键作用。然而&#xff0c;在实践过程中&#xff0c;这两种技术也存在一些痛点和挑战。 DNA亲和…

丹摩征文活动| 摩智云端深度解析:Faster R-CNN模型的训练与测试实战指南

目录 丹摩简介 文章前言Faster R-CNN的简介Faster RCNN的训练与测试提前准备1.1 mobaxterm&#xff08;远程连接服务器&#xff09;1.2 本文的源码下载 目标检测模型 Faster-Rcnn2.1云服务器平台 数据上传内置JupyterLab的使用本地连接使用DAMODEL实例获取实例的SSH访问信息通过…

二叉搜索树介绍

⼆叉搜索树 二叉搜索树的概念二叉搜索树的性能分析查找性能插入性能删除性能 二叉搜索树的插入二叉搜索树的查找二叉搜索树的删除⼆叉搜索树的实现代码测试代码 二叉搜索树key和key/value使⽤场景key搜索场景key/value搜索场景key/value⼆叉搜索树代码实现测试代码 二叉搜索树的…

7.揭秘C语言输入输出内幕:printf与scanf的深度剖析

揭秘C语言输入输出内幕&#xff1a;printf与scanf的深度剖析 C语言往期系列文章目录 往期回顾&#xff1a; VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础概念&#xff0c;动手实现首个C程序C语言概念之旅&#xff1a;解锁关…

5.4.2-1 编写Java程序在HDFS上创建文件

本次实战涉及使用Java操作Hadoop HDFS&#xff0c;包括创建文件、判断文件存在性及异常处理。通过手动添加依赖、启动HDFS服务&#xff0c;成功在HDFS上创建和检查文件。进一步探索了文件操作的最佳实践&#xff0c;如检查文件存在性以避免重复创建&#xff0c;以及处理HDFS安全…

RabbitMQ教程:路由(Routing)(四)

文章目录 RabbitMQ教程&#xff1a;路由&#xff08;Routing&#xff09;&#xff08;四&#xff09;一、引言二、基本概念2.1 路由与绑定2.2 Direct交换机2.3 多绑定2.4 发送日志2.5 订阅 三、整合代码3.1 EmitLogDirectApp.cs3.2 ReceiveLogsDirectApp.cs3.3 推送所有和接收e…

智云-一个抓取web流量的轻量级蜜罐v1.5

智云-一个抓取web流量的轻量级蜜罐v1.5 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN 新增功能-自定义漏洞信息 可通过正则来添加相关路由以及响应来伪造 nacos的版本响应如下 日流量态势 月流量态势 抓取流量效果

21.UE5游戏存档,读档,函数库

2-23 游戏存档、读档、函数库_哔哩哔哩_bilibili 目录 1.存档蓝图 2.函数库 2.1保存存档 2.2读取存档&#xff1a; 3.加载游戏&#xff0c;保存游戏 3.1游戏实例对象 3.2 加载游戏 3.3保存游戏 这一节的内容较为错综复杂&#xff0c;中间没有运行程序进行阶段性成果的验…

实验5:网络设备发现、管理和维护

实验5&#xff1a;网络设备发现、管理和维护 实验目的及要求&#xff1a; 通过实验&#xff0c;掌握Cisco 路由器和交换机的IOS配置管理。自动从NTP服务器获取时间信息。能够利用TFTP服务器实现路由器和交换机配置文件的备份和恢复。同时验证CDP协议和LLDP协议的网络参数。完…

vue 项目使用 nginx 部署

前言 记录下使用element-admin-template 改造项目踩过的坑及打包部署过程 一、根据权限增加动态路由不生效 原因是Sidebar中路由取的 this.$router.options.routes,需要在计算路由 permission.js 增加如下代码 // generate accessible routes map based on roles const acce…

DataWorks on EMR StarRocks,打造标准湖仓新范式

在大数据领域&#xff0c;数据仓库和实时分析系统扮演着至关重要的角色。DataWorks 基于大数据引擎&#xff0c;为数据仓库/数据湖/湖仓一体等解决方案提供统一的全链路大数据开发治理平台&#xff0c;为用户带来智能化的数据开发和分析体验。而阿里云提供的 EMR Serverless St…

七、利用CSS和多媒体美化页面的习题

题目一&#xff1a; 利用CSS技术&#xff0c;结合表格和列表&#xff0c;制作并美化 “ 翡翠阁 ”页面。运行效果如下 运行效果&#xff1a; 代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>翡翠阁</title>&…

游戏引擎学习第15天

视频参考:https://www.bilibili.com/video/BV1mbUBY7E24 关于游戏中文件输入输出&#xff08;IO&#xff09;操作的讨论。主要分为两类&#xff1a; 只读资产的加载 这部分主要涉及游戏中用于展示和运行的只读资源&#xff0c;例如音乐、音效、美术资源&#xff08;如 3D 模型和…

【动手学深度学习Pytorch】2. Softmax回归代码

零实现 导入所需要的包&#xff1a; import torch from IPython import display from d2l import torch as d2l定义数据集参数、模型参数&#xff1a; batch_size 256 # 每次随机读取256张图片 train_iter, test_iter d2l.load_data_fashion_mnist(batch_size) # 将展平每个…