Vue插槽Slot的使用

news2024/12/26 3:27:59

1、认识插槽Slot

在开发中,我们会经常封装一个个可复用的组件:

  • 前面我们会通过props传递给组件一些数据,让组件来进行展示;
  • 但是为了让这个组件具备更强的通用性,我们不能将组件中的内容限制为固定的div、span等等这些元素;
  • 比如某种情况下我们使用组件,希望组件显示的是一个按钮,某种情况下我们使用组件希望显示的是一张图片;
  • 我们应该让使用者可以决定某一块区域到底存放什么内容和元素

举个栗子:假如我们定制一个通用的导航组件 - NavBar

  • 这个组件分成三块区域:左边-中间-右边,每块区域的内容是不固定;
  • 左边区域可能显示一个菜单图标,也可能显示一个返回按钮,可能什么都不显示;
  • 中间区域可能显示一个搜索框,也可能是一个列表,也可能是一个标题,等等;
  • 右边可能是一个文字,也可能是一个图标,也可能什么都不显示;

 

2、使用插槽slot

这个时候我们就可以来定义插槽slot:

  • 插槽的使用过程其实是抽取共性、预留不同
  • 我们会将共同的元素、内容依然在组件内进行封装;
  • 同时会将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素;

如何使用slot呢?

  • Vue中将 <slot> 元素作为承载分发内容的出口;
  • 在封装组件中,使用特殊的元素<slot>就可以为封装组件开启一个插槽
  • 该插槽插入什么内容取决于父组件如何使用;

 

3、插槽的默认内容

有时候我们希望在使用插槽时,如果没有插入对应的内容,那么我们需要显示一个默认的内容

  • 当然这个默认的内容只会在没有提供插入的内容时,才会显示;

 

4、多个插槽的效果

我们先测试一个知识点:如果一个组件中含有多个插槽,我们插入多个内容时是什么效果?

  • 我们会发现默认情况下每个插槽都会获取到我们插入的内容来显示;

 

5、插槽的基本使用

  • 我们一个组件MySlotCpn.vue:该组件中有一个插槽,我们可以在插槽中放入需要显示的内容;
  • 我们在App.vue中使用它们:
    • 我们可以插入普通的内容、html元素、组件,都可以是可以的;

示例代码: 

ShowMessage.vue

<template>
  <h2>{{ title }}</h2>
  <div class="content">
    <slot>
      <p>我是默认内容, 哈哈哈</p>
    </slot>
  </div>
</template>

<script>
  export default {
    props: {
      title: {
        type: String,
        default: "我是title默认值"
      }
    }
  }
</script>

<style scoped>
</style>

App.vue 

<template>
  <div class="app">
    <!-- 1.内容是button -->
    <show-message title="哈哈哈">
      <button>我是按钮元素</button>
    </show-message>

    <!-- 2.内容是超链接 -->
    <show-message>
      <a href="#">百度一下</a>
    </show-message>

    <!-- 3.内容是一张图片 -->
    <show-message>
      <img src="@/img/kobe02.png" alt="">
    </show-message>

    <!-- 4.内容没有传递 -->
    <show-message></show-message>
  </div>
</template>

<script>
  import ShowMessage from './ShowMessage.vue'

  export default {
    components: {
      ShowMessage
    }
  }
</script>

<style scoped>
</style>

6、具名插槽的使用

事实上,我们希望达到的效果是插槽对应的显示,这个时候我们就可以使用 具名插槽

  • 具名插槽顾名思义就是给插槽起一个名字,<slot> 元素有一个特殊的 attribute:name;
  • 一个不带 name 的slot,会带有隐含的名字 default

6.1、动态插槽名 

什么是动态插槽名呢?

  • 目前我们使用的插槽名称都是固定的;
  • 比如 v-slot:left、v-slot:center等等;
  • 我们可以通过 v-slot:[dynamicSlotName] 方式动态绑定一个名称;

6.2、具名插槽使用的时候缩写 

具名插槽使用的时候缩写:

  • 跟 v-on 和 v-bind 一样,v-slot 也有缩写
  • 即把参数之前的所有内容 (v-slot:) 替换为字符 #

6.3、示例: 

NavBar.vue

<template>
  <div class="nav-bar">
    <div class="left">
      <slot name="left">left</slot>
    </div>
    <div class="center">
      <slot name="center">center</slot>
    </div>
    <div class="right">
      <slot name="right">right</slot>
    </div>
  </div>

  <div class="other">
    <slot name="default"></slot>
  </div>
</template>

<script>
  export default {

  }
</script>

<style scoped>
  .nav-bar {
    display: flex;
    height: 44px;
    line-height: 44px;
    text-align: center;
  }

  .left {
    width: 80px;
    background-color: orange;
  }

  .center {
    flex: 1;
    background-color: skyblue;
  }

  .right {
    width: 80px;
    background-color: aquamarine;
  }
</style>

App.vue

<template>
  <nav-bar>
    <template #left>
      <button>{{ leftText }}</button>
    </template>

    <template #center>
      <span>内容</span>
    </template>

    <template v-slot:right>
      <a href="#">登录</a>
    </template>
  </nav-bar>

  <!-- nav-bar只给一个插槽传入数据 -->
  <nav-bar>
    <template v-slot:[position]>
      <a href="#">注册</a>
    </template>
  </nav-bar>
  <button @click=" position = 'left' ">左边</button>
  <button @click=" position = 'center' ">中间</button>
  <button @click=" position = 'right' ">右边</button>
</template>

<script>
  import NavBar from './NavBar.vue'

  export default {
    components: {
      NavBar
    },
    data() {
      return {
        position: "center",
        leftText: "返回"
      }
    }
  }
</script>

<style scoped>
</style>

7、作用域插槽的使用

7.1、渲染作用域

  • 在Vue中有渲染作用域的概念:
    • 父级模板里的所有内容都是在父级作用域中编译的
    • 子模板里的所有内容都是在子作用域中编译的
  • 如何理解这句话呢?我们来看一个案例:
    • 在我们的案例中ChildCpn自然是可以让问自己作用域中的title内容的;
    • 但是在App中,是访问不了ChildCpn中的内容的,因为它们是跨作用域的访问;

7.2、认识作用域插槽 

但是有时候我们希望插槽可以访问到子组件中的内容是非常重要的:

  • 当一个组件被用来渲染一个数组元素时,我们使用插槽,并且希望插槽中没有显示每项的内容;
  • 这个Vue给我们提供了作用域插槽

我们来看下面的一个案例:

  1. 在App.vue中定义好数据
  2. 传递给ShowNames组件中
  3. ShowNames组件中遍历names数据
  4. 定义插槽的prop
  5. 通过v-slot:default的方式获取到slot的props
  6. 使用slotProps中的item和index

7.3、独占默认插槽的缩写 

        如果我们的插槽是默认插槽default,那么在使用的时候 v-slot:default="slotProps"可以简写为v-slot="slotProps":

        并且如果我们的插槽只有默认插槽时,组件的标签可以被当做插槽的模板来使用,这样,我们就可以将 v-slot 直接用在组件上:

7.4、默认插槽和具名插槽混合 

但是,如果我们有默认插槽和具名插槽,那么按照完整的template来编写。

只要出现多个插槽,请始终为所有的插槽使用完整的基于 <template> 的语法:

7.5、示例

TabControl.vue

<template>
  <div class="tab-control">
    <template v-for="(item, index) in titles" :key="item">
      <div class="tab-control-item"
           :class="{ active: index === currentIndex }"
           @click="itemClick(index)">
        <slot :item="item" abc="cba">
          <span>{{ item }}</span>
        </slot>
      </div>
    </template>
  </div>
</template>

<script>
  export default {
    props: {
      titles: {
        type: Array,
        default: () => []
      }
    },
    data() {
      return {
        currentIndex: 0
      }
    },
    emits: ["tabItemClick"],
    methods: {
      itemClick(index) {
        this.currentIndex = index
        this.$emit("tabItemClick", index)
      }
    }
  }
</script>

<style scoped>
  .tab-control {
    display: flex;
    height: 44px;
    line-height: 44px;
    text-align: center;
  }

  .tab-control-item {
    flex: 1;
  }

  .tab-control-item.active {
    color: red;
    font-weight: 700;
  }

  .tab-control-item.active span {
    border-bottom: 3px solid red;
    padding: 8px;
  }
</style>

App.js

<template>
  <div class="app">
    <!-- 1.tab-control -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick"/>

    <!-- <tab-control :titles="['流行', '最新', '优选']"/> -->

    <!-- 2.展示内容 -->
    <h1>{{ pageContents[currentIndex] }}</h1>

    <!-- 1.tab-control: button -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick">
      <template v-slot:default="props"> <!--这个名字是自定义的-->
        <button>{{ props.item }}</button>
      </template>
    </tab-control>

    
    <!-- 2.tab-control: a元素(重要) -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick">
      <template #default="props">
        <a href="#">{{ props.item }}</a>
      </template>
    </tab-control>

    <!-- 3.独占默认插槽的简写(了解) -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick">
      <template v-slot="props">
        <button>{{ props.item }}</button>
      </template>
    </tab-control>

    <!-- 4.如果只有一个默认插槽, 那么template可以省略 -->
    <tab-control :titles="['衣服', '鞋子', '裤子']" 
                 @tab-item-click="tabItemClick"
                 v-slot="props">
      <button>{{ props.item }}</button>
    </tab-control>
  </div>
</template>

<script>
  import TabControl from './TabControl.vue'

  export default {
    components: {
      TabControl
    },
    data() {
      return {
        pageContents: [ "衣服列表", "鞋子列表", "裤子列表" ],
        currentIndex: 0
      }
    },
    methods: {
      tabItemClick(index) {
        console.log("app:", index)
        this.currentIndex = index
      }
    }
  }
</script>

<style scoped>
</style>

main.js

import { createApp } from 'vue'

import App from './App.vue'

createApp(App).mount('#app')

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

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

相关文章

【零基础】学python数据结构与算法笔记15-欧几里得、RSA

文章目录前言95.欧几里得算法96.RSA算法介绍97.RSA算法测试98.算法课程总结总结前言 学习python数据结构与算法&#xff0c;学习常用的算法&#xff0c; b站学习链接 95.欧几里得算法 求最大公约数 欧几里得算法&#xff1a;gcd(a,b) gcd(b,a mod b) #mod取余 例&#xff1a…

04.自定义类型:结构体

1 结构体的声明 1.1 结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量。 1.2 结构的声明 struct tag { member-list;//成员列表 }variable-list;//变量列表 EG: 描述一位学生&#xff1a; struct Stu {char name[…

Comparable+Comparator+Cloneable接口

文章目录ComparableComparatorCloneable浅拷贝深拷贝Comparable 当我们需要对一个自己写的类进行排序(Collections.sort和Arrays.sort)的时候&#xff0c;,就要使用到Comparable接口。 该接口中有一个compareTo方法&#xff0c;该方法其实就是一比较规则。 public interface…

货币银行学

建立大脑知识库 外汇储备不宜太高&#xff0c;2022年是3万亿。 美元贬值&#xff0c;大宗商品会更贵。 大宗商品 [1] &#xff08;Commodities&#xff09;是指可进入流通领域&#xff0c;但非零售环节&#xff0c;具有商品属性并用于工农业生产与消费使用的大批量买卖的物质商…

Oracle Id生成算法 —— 雪花算法

背景 近几日&#xff0c;被主键ID生成折磨的不太行&#xff0c;于是就在寻找一种合适的主键生成策略&#xff0c;选择一种合适的主键生成策略&#xff0c;可以大大降低主键ID的维护成本。 主键ID生成方法 最常用的4种主键ID生成方法 UUID&#xff1a;全局唯一性&#xff0c…

【框架】Spring

1、IOC 1、自动化配置 xml文件 注册bean 属性注入&#xff1a;setter&#xff0c;构造方法&#xff0c;p命名空间&#xff0c;外部注入 复杂属性&#xff1a;对象ref&#xff0c;数组array&#xff0c;list&#xff0c;map 依赖注入&#xff1a;ctx.getBean()Java配置类 Conf…

InterruptedException异常解析

Either re-interrupt this method or rethrow the “InterruptedException”. 请重新中断此方法或重新引发“InterruptedException”。 文章目录问题描述问题解析sonar检测提示规则解决方案问题描述 public void run () {try {while (true) {// do stuff}}catch (InterruptedE…

webgl变换矩阵理论详解

文章目录前言矩阵运算矩阵加减矩阵数乘矩阵乘矩阵矩阵转置逆矩阵正交矩阵矩阵变换的一般规则行主序和列主序行向量和列向量复杂变换时的顺序变换矩阵进行图形变换uniform传递矩阵平移缩放旋转组合变换实例总结前言 在webgl中将图形进行平移、旋转、缩放等操作时可以在着色器中…

11.1 使用关联容器

文章目录关联容器的类型使用map使用set关联容器中元素是按关键字保存和访问的&#xff0c;支持高效关键字查找和访问。顺序容器中元素是按他们在容器中的位置保存访问的。关联容器有两个主要类型&#xff1a;set和map。 set&#xff1a;每个元素包含一个关键字&#xff0c;想知…

OPC实践:通过 python-docx 读取 docx 文档

概述 本文记录下列命令执行的过程&#xff0c;通过对过程中的关键步骤进行记录&#xff0c;掌握 python-docx 库中 opc 与 parts 模块的源码、以及加深对 OPC 的理解。 import docx# fp 为 docx 文件路径&#xff0c; docx 包含一个 hello 字符串、一张 jepg 图片及一个表格…

<Python的列表和元组>——《Python》

目录 1.列表 1.1 列表的概念 1.2 创建列表 1.3 访问下标 1.4 切片操作 1.5 遍历列表元素 1.6 新增元素 1.7 查找元素 1.8 删除元素 1.9 连接列表 2. 元组 1.列表 1.1 列表的概念 编程中, 经常需要使用变量, 来保存/表示数据. 如果代码中需要表示的数据个数比较少,…

初识 Bootstrap(前端开发框架)

初识 Bootstrap&#xff08;前端开发框架&#xff09;参考Bootstrap特点获取目录结构jQuery 与 Popper准备工作包含 jQuery 与 Poppermetabox-sizing基本模板无注释版本注释版本参考 项目描述Bootstrap 官方教程https://getbootstrap.net/docs/getting-started/introduction/百…

字节青训前端笔记 | HTTP 使用指南

本节课介绍 Http 协议的基本定义和特点&#xff0c;在此基础上&#xff0c;对于 Http 协议的发展历程及报文结构展开进一步分析。 从输入字符串到打开网页 输入地址浏览器处理输入信息浏览器发请求到达服务器服务器返回信息浏览器读取响应信息浏览器渲染页面加载完成 什么是…

KVM虚拟化简介 | 初识

目录 1、kvm架构 2、架构解析 3、kvm和qemu的作用 1、kvm架构 2、架构解析 从rhel6开始使用&#xff0c;红帽公司直接把KVM的模块做成了内核的一部分。xen用在rhel6之前的企业版中默认内核不支持&#xff0c;需要重新安装带xen功能的内核KVM 针对运行在x86 硬件上的、驻留在内…

配置 Git 连接 GitHub

文章目录0.安装 Git1.注册 GitHub 账号2.配置 Git 的用户名和邮箱3.为本机生成 SSH 密钥对4.将公钥拷贝到 GitHub 上5.测试0.安装 Git Git 官网链接&#xff1a;https://git-scm.com/ Git 官网下载链接&#xff1a;https://git-scm.com/downloads 1.注册 GitHub 账号 GitHu…

蓝桥杯STM32G431RBT6学习——定时器PWM输出

蓝桥杯STM32G431RBT6学习——定时器PWM输出 前言 PWM波输出作为定时器的一个常用功能&#xff0c;也属于高频的考点。从数据手册的定时器解析可以了解到&#xff08;上篇描述&#xff09;&#xff1a;除了基本定时器&#xff08;TIM6、7&#xff09;外&#xff0c;其他所有定…

全国产网管型工业交换机的几种管理方式

全国产网管型工业交换机按其字面上的意思&#xff0c;一是全国产化&#xff08;工业交换机&#xff09;&#xff0c;就是交换机内部95%以上元器件的国内生产制造&#xff0c;重要的硬件芯片&#xff0c;比如交换机芯片、管理芯片、接口芯片等必须是国内厂商在国内研发、生产、制…

学习记录664@项目管理之项目进度管理

什么是项目进度管理 项目进度管理包括为管理项目按时完成所需的7个过程&#xff0c;具体为: 规划进度管理过程一一制定政策、程序和文档以管理项目进度。定义活动过程一一识别和记录为完成项目可交付成果而需采取的具体行动。排列活动顺序过程一一识别和记录项目活动之间的关…

【Kubernetes 企业项目实战】04、基于 K8s 构建 EFK+logstash+kafka 日志平台(下)

目录 一、安装收集日志组件 Fluentd 二、kibana 可视化展示查询 k8s 容器日志 三、测试 efk 收集生产环境业务 pod 日志 四、基于 EFKlogstashkafka 构建高吞吐量的日志平台 4.1 部署 fluentd 4.2 接入 kafka 4.3 配置 logstash 4.4 启动 logstash 本篇文章所用到的资料…

对象的比较

Java中基本类型间的元素比较&#xff0c;可以直接通过">"、"<"、""等符号判断大小&#xff0c;也可使用compareTo比较大小或者equals判断是否相等&#xff0c;作为引用类型的String类不可以使用">"、"<"比较大小…