Vue之插槽(slot)

news2024/12/26 11:45:30

插槽是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>

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

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

相关文章

华为鸿蒙HarmonyOS NEXT升级HiCar:打造未来出行新体验

随着科技的不断进步&#xff0c;智能出行已成为我们生活中不可或缺的一部分。华为凭借其在智能科技领域的深厚积累&#xff0c;推出了全新的鸿蒙HarmonyOS NEXT系统&#xff0c;旨在为用户打造一个“人车家”的无缝协同出行体验。这一系统的核心亮点之一&#xff0c;就是其内置…

Clickhouse集群新建用户、授权以及remote权限问题

新建用户 create user if not exists user on cluster 集群名称 IDENTIFIED WITH plaintext_password BY 密码;给用户授查询、建表、删表的权限 GRANT create table,select,drop table ON 数据库实例.* TO user on cluster 集群名称 ;在其他节点下用户建本地表成功&#…

Serverless架构在实时数据处理中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 Serverless架构在实时数据处理中的应用 Serverless架构在实时数据处理中的应用 Serverless架构在实时数据处理中的应用 引言 Ser…

Scrapy爬取heima论坛所有页面内容并保存到数据库中

前期准备&#xff1a; Scrapy入门_win10安装scrapy-CSDN博客 新建 Scrapy项目 scrapy startproject mySpider03 # 项目名为mySpider03 进入到spiders目录 cd mySpider03/mySpider03/spiders 创建爬虫 scrapy genspider heima bbs.itheima.com # 爬虫名为heima &#…

QSS 设置bug

问题描述&#xff1a; 在QWidget上add 一个QLabel&#xff0c;但是死活不生效 原因&#xff1a; c 主程序如下&#xff1a; QWidget* LOGO new QWidget(logo_wnd);LOGO->setFixedSize(logo_width, 41);LOGO->setObjectName("TittltLogo");QVBoxLayout* tit…

TKinter实现与Dash应用的同步启停控制

使用Python集成Tkinter和Dash&#xff1a;创建交互式数据可视化应用 在数据可视化项目中&#xff0c;我们经常需要结合传统GUI和现代Web可视化框架的优势。本文将介绍如何整合Tkinter和Dash&#xff0c;创建一个既有桌面应用界面&#xff0c;又能展示交互式图表的应用程序。 …

FreeRTOS学习13——任务相关API函数

任务相关API函数 任务相关API函数任务相关API函数介绍任务相关 API 函数详解函数 uxTaskPriorityGet()函数 vTaskPrioritySet()函数 uxTaskGetSystemState()函数 vTaskGetInfo()函数 xTaskGetApplicationTaskTag()函数 xTaskGetCurrentHandle()函数 xTaskGetHandle()函数 xTask…

2022-2023全国高校计算机能力挑战赛区域赛python组编程题

mi目录 2022 1. 2. 1. 使用 format() 方法 2. 使用 f-string&#xff08;Python 3.6 及以上&#xff09; 2023 1. 2. 3. 4 闽农大宝玲楼 2022 1. 1.某动物研究员给动物园的动物们定了一个园区幸福值&#xff0c;其中园区幸福值的计算为一个园区内“所有动物的活动时…

在Element Ui中支持从系统粘贴版中获取图片和PDF,Docx,Doc,PPT等文档

在上一篇中&#xff0c;我们单纯的实现了Ctrl V实现从粘贴版中获取图片信息&#xff0c;但是点击上传的时候会有个bug&#xff0c;就是点击文件上传的时候&#xff0c;会出现一个bug&#xff0c;这篇&#xff0c;我们将在上一篇的基础上进行完善&#xff0c;并支持从粘贴版中获…

【Android学习】2024最新版Android Studio安装与配置

准备工作 Windows系统的要求 一、下载 Android Studio官网&#xff1a;https://developer.android.google.cn/studio?hlen 今天是2024年9月27日&#xff0c;Android Studio已经更新到了Koala版本 直接下载 二、安装 笔者当前环境变量中配置的JDK版本为1.8 双击.exe文件运行…

如何解决JAVA程序通过obloader并发导数导致系统夯住的问题 | OceanBase 运维实践

案例背景 某保险机构客户的数据中台&#xff0c;自系统上线后不久&#xff0c;会定期的用 obload 工具从上游业务系统导入数据至OceanBase数据库。但&#xff0c;不久便遇到了应用服务器的 Memory 与 CPU 资源占用持续攀升&#xff0c;最终导致系统夯住而不可用的异常。 memo…

2分钟在阿里云ECS控制台部署个人应用(图文示例)

作为一名程序员&#xff0c;我有大量的个人代码和应用托管在Github/Gitee这些代码仓库。当我想要部署这些代码到我的阿里云ECS服务器时&#xff0c;往往会很麻烦&#xff0c;主要问题有这些&#xff1a; 需要手动安装和配置git&#xff0c;过程非常繁琐。每次都需要登录到机器…

Oracle XE命令行创建数据库的一波三折(已解决)

这是一个目录 前言创建预备创建一、创建配置文件指定控制文件路径二、使用命令行创建数据库三、初始化数据库四、创建服务五、配置监听 Oracle XE尾声 前言 这篇文章是我在误装了oracle xe&#xff08;精简版数据库&#xff09;后有感而写&#xff0c;对于xe的具体区别将在文末…

第四十一章 Vue之初识VueX

目录 一、引言 1.1. vuex的概念 1.2. vuex使用场景 1.3. 优势 二、创建演示项目 2.1. 构建项目步骤 2.2. 项目最终生成结构 2.3. 创建项目文件 2.3.1. App.vue 2.3.2. Son1.vue 2.3.3. Son2.vue 三、创建一个空仓库 3.1. 安装vuex 3.2. 新建仓库 3.3. 挂载仓库…

机器学习-35-提取时间序列信号的特征

文章目录 1 特征提取方法1.1 特征提取过程1.2 两类特征提取方法2 基于数据驱动的方法2.1 领域特定特征提取2.2 基于频率的特征提取2.2.1 模拟信号2.2.2 傅里叶变换2.2.3 抽取最大幅值对应特征2.2.4 抽取峰值幅值对应特征2.3 基于统计的特征提取2.4 基于时间的特征提取3 参考附录…

My_SQL day3

知识点&#xff1a;约束 1.dafault 默认约束 2.not null 非空约束 3.unique key 唯一约束 4.primary key 主键约束 5.anto_increment 自增长约束 6.foreign key 外键约束 知识点&#xff1a;表关系 1.一对一 2.一对多 3.多对多 知识点&#xff1a;约束 1.default 默认约束 …

caozha-CEPCS(新冠肺炎疫情防控系统)

caozha-CEPCS&#xff0c;是一个基于PHP开发的新冠肺炎疫情防控系统&#xff0c;CEPCS&#xff08;全称&#xff1a;COVID-19 Epidemic Prevention and Control System&#xff09;&#xff0c;可以应用于单位、企业、学校、工业园区、村落等等。小小系统&#xff0c;希望能为大…

深度学习推荐系统的工程实现

参考自《深度学习推荐系统》——王喆&#xff0c;用于学习和记录。 介绍 之前章节主要从理论和算法层面介绍了推荐系统的关键思想。但算法和模型终究只是“好酒”&#xff0c;还需要用合适的“容器”盛载才能呈现出最好的味道&#xff0c;这里的“容器”指的就是实现推荐系统…

2024 年(第 7 届)“泰迪杯”数据分析技能赛B 题 特殊医学用途配方食品数据分析 完整代码 结果 可视化分享

一、背景特殊医学用途配方食品简称特医食品&#xff0c;是指为满足进食受限、消化吸收障碍、代谢素乱或者特定疾病状态人群对营养素或者膳食的特殊需要&#xff0c;专门加工配置而成的配方食品&#xff0c;包括0月龄至12月龄的特殊医学用途婴儿配方食品和适用于1岁以上的特殊医…

Ubuntu 的 ROS 2 操作系统安装与测试

引言 机器人操作系统&#xff08;ROS, Robot Operating System&#xff09;是一种广泛应用于机器人开发的开源框架&#xff0c;提供了丰富的库和工具&#xff0c;支持开发者快速构建、控制机器人并实现智能功能。 当前&#xff0c;ROS 2 的最新长期支持版本为 Humble Hawksbil…