深入理解Vue slot的原理

news2024/9/25 9:30:36

文章目录

  • 前言
  • 为什么需要插槽
  • 作用域插槽
  • 插槽的原理
  • 总结

前言

插槽是Vue中一个重要的特性,它有很多种用法:默认插槽、具名插槽、作用域插槽。尤其作用域插槽,还有一堆特性,比如解构prop,解构prop的时候还可以进行属性名的映射。
记不住,根本记不住。
死记硬背当然记不住,但只要了解了原理,这些根本不用记。

为什么需要插槽

在深入原理之前,我们还是巩固一下基础。
为什么我们需要插槽这个特性,插槽到底是什么?
如果你看的是Vue2的文档,那么你会一头雾水:
在这里插入图片描述
Vue2几乎是没什么铺垫,上来就给你介绍插槽的特性。所以插槽到底是什么,为什么要用这个东西,得你自己悟。
Vue3的文档稍微好一点:
在这里插入图片描述
Vue3的文档说到了插槽的一些关键的点,但仍然很隐晦。
这里我们戳破这层窗户纸,给插槽一个明确的定义:

  1. 插槽给是组件的一种传参方式。组件可以通过props传参,也可以通过插槽传参。
  2. props传参传的是对象或值,插槽传的是模板内容
  3. 使用插槽的目的是将一部分由子组件负责的渲染工作交给父组件定义,提高的组件的灵活性

为什么要使用插槽呢?接下来我通过一个例子来说明。
现在假设你要实现一个无序列表的组件,基本长下面这样:
在这里插入图片描述
但是用户可能不满足于此,他们希望能让选项的字体加粗,或者变成斜体,或者改变字体颜色,或者在选项前面增加图标。更有甚者,他们希望选项的内容可以是更加复杂的DOM结构。

怎么办?如果没有插槽,你只能给组件提供足够多的props,让用户通过设置这些props来定制自己想要的效果。用户有新的需求,你也要跟着修改。

用插槽就可以完美解决这个问题。
我们定义一个组件List:

<script setup>
  let props = defineProps(['data'])
</script>

<template>
   <ul>
     <li v-for="item in props.data">
         <slot v-bind="item">{{item.text}}</slot>
     </li>
   </ul>
</template>

父组件可以这么用:

<script setup>
import { ref } from 'vue'
import List from './List.vue';

const data = [ {text: 'Java' }, { text: 'PHP'}, { text: 'CSS'} ]
</script>

<template>
  <List :data />
</template>

这里使用的是后备内容,所以就是平平无奇的展示。
在这里插入图片描述

如果父组件想要让文字加粗或者使用斜体或改变颜色,它可以自己定义:

<template v-slot="data">
   <b><i>{{data.text}}</i></b>
 </template>

List组件不需要做任何改动。

作用域插槽

这里我们不在赘述默认插槽、具名插槽,这没啥好说的,我们直接来看作用域插槽。
作用域插槽的难点就在解构prop上,写法有很多种,比如:

<template v-slot="{ user }">
   {{ user.name }}
</template>

你有没有想过为啥user要包裹一个花括号,你也可以不包裹:

<template v-slot="scope">
   {{ scope.user.name }}
</template>

你还可以进行属性映射:

<template v-slot="{ user: person }">
   {{ person.name }}
</template>

你还可以这样:

<template v-slot="{ user = { name: 'Guest' } }">
   {{ user.name }}
</template>

不是,这都是啥,直接懵了呀。

  • 我为什么要加括号,什么时候不加
  • 属性映射是个啥,有啥用呀
  • 解构的时候还可以提供默认值?
  • 还有这是Vue的模板语法,还是JS的语法呀

有这些疑问都是因为不熟悉插槽的原理。不熟悉原理就只能死记硬背,熟悉了,根本就不用记。
在vue2的文档里面有对解构的原理进行解释:
在这里插入图片描述
所以这些语法不是Vue创造的,而是ES2015的函数参数解构的语法,比如:
普通的参数解构

function test({ name }) {
	console.log(name)
}

let user = { name: '张三', age: 18 }
test(user) // 张三

解构的时候提供默认值:

function test({ name='张三' }) {
	console.log(name)
}

let user = { age: 18 }
test(user) // 张三
user.name = '李四'
test(user) // 李四

解构的时候进行属性映射:

function test({ name: userName}) {
	console.log(userName)
}

let user = { name: '张三', age: 18 }
test(user) // 张三

只要这种参数解构的语法是JS支持的,那么Vue的插槽就是支持的,你还需要死记硬背吗。

插槽的原理

最后我们终于要系统性的看看插槽是怎么实现的了,我们可以在Vue的Playground看看插槽编译后的结果。
子组件编译后的关键代码:
在这里插入图片描述
子组件的render函数中通过调用renderSlot方法来渲染插槽,你可以认为子组件会去调用:

_ctx.$slots.default({item})

如果父组件没有提供插槽的模板,子组件就会渲染后备内容,也就是:

_createTextVNode(_toDisplayString(item.text), 1 /* TEXT */)

接下来我们再看看父组件编译后的关键代码:
在这里插入图片描述
父组件通过createBlock渲染子组件,第三个参数传的是插槽的实现,default就是默认插槽的名字(如果是具名插槽,那么就是对应插槽的名字)。
我通过JS的高阶函数来模拟这个过程,让大家更容易理解这个原理。
现在假设我一个函数list:

function list(consumer) {
	const data = [ {text: 'Java' }, { text: 'PHP'}, { text: 'CSS'} ]
	for (let item of data) {
       consumer(item)
    }
}

list函数可以通过接收一个consumer,让调用方来控制输出的方式。
调用方,可以这样:

list((data) => console.log(data.text))
// Java
// PHP
// CSS

也可以控制输出,比如:

list((data) => console.log('==', data.text, '=='))
// ==Java==
// ==PHP==
// ==CSS==

也可以解构:

list(({text}) => console.log(text))
// Java
// PHP
// CSS

这样是不是更容易理解了。
父组件不同的插槽实现,编译出来的结果也不一样,这就是vue的编译器要做的事情了。
比如,我们看看prop解构的时候,编译的结果是什么样子的。
没有解构的情况:

<template v-slot="data">
      {{data.text}}
    </template>

编译后:
在这里插入图片描述
有解构:

<template v-slot="{text}">
      {{text}}
    </template>

编译后:
在这里插入图片描述
解构的时候进行属性映射:

<template v-slot="{text: name}">
      {{name}}
    </template>

编译后:
在这里插入图片描述
提供参数默认值:
在这里插入图片描述
是不是一模一样!所以这块就是用的JS的语法特性。

什么时候需要进行解构,什么时候不需要呢,这取决于父组件需要关注哪些prop。
子组件定义插槽的时候,可以绑定多个属性,比如:

<slot :text="item.text" :icon="item.icon">{{item.text}}</slot>

编译后的结果如下:
在这里插入图片描述
如果父组件提供插槽内容的时候只使用text,那么就可以只解构出text属性。

<template v-slot="{ text }">
      {{text}}
    </template>

如果text和icon都要用到,那么就都解构:

<template v-slot="{ text, icon }">
      <i class="fa" :class="'fa-' + icon"></i><span>{{text}}</span>
    </template>

或者不解构:

<template v-slot="item">
      <i class="fa" :class="'fa-' + item.icon"></i><span>{{item.text}}</span>
    </template>

这些都不需要死记硬背,你知道了原理,知道了父组件v-slot的内容就是子组件所有bind的属性组成的对象,知道了它的结构,你就知道要不要解构,以及可以怎么解构。

总结

总结一下,最重要的三个结论:

  1. 插槽是一种组件的传参方式,可以传递模板内容,可以提高组件的灵活性
  2. 插槽的本质就是JS的高阶函数,函数由父组件实现,子组件调用
  3. 插槽的prop解构不是vue的语法,本质就是ES6方法参数的解构语法

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

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

相关文章

[CISCN2019 华北赛区 Day2 Web1]Hack World1

试试数字1 2 3朝后都是 猜测为数字型注入 试试1 union select flag from flag 爆破发现都被过滤了&#xff0c;尝试用布尔盲注&#xff0c;用python编写脚本&#xff0c;得到flag

浅谈SPI

目录 前言JDK SPIJDBC SPIServiceLoader实现原理小结 SpringSpringBoot SPI实现原理Debug小结 Dubbo SPI如何使用实现原理 前言 SPI&#xff0c;英文全称是Service Provider Interface&#xff0c;直译是“服务提供接口”或“服务提供者接口”&#xff0c;是一种基于ClassLoad…

YOLOv8目标检测算法改进之融合SCconv的特征提取方法

引言 YOLO目标检测算法历经发展&#xff0c;目前已经成为了目标检测领域的经典算法。当前&#xff0c;YOLO目标检测算法已经更新到YOLOv10&#xff0c;但从大家的反映来看,YOLOv10的效果并不理想&#xff08;该算法的创新点是提升检测速度&#xff0c;并不提升精度&#xff0c…

JVM: 方法调用

文章目录 一、介绍二、方法调用的原理1、静态绑定2、动态绑定&#xff08;1&#xff09;介绍&#xff08;2&#xff09;原理 一、介绍 在JVM中&#xff0c;一共有五个字节码指令可以执行方法调用&#xff1a; invokestatic: 调用静态方法。invokespecial&#xff1a;调用对象…

大模型参与城市规划中的应用

人工智能咨询培训老师叶梓 转载标明出处 传统的城市规划往往依赖于专业规划师的经验和判断&#xff0c;耗时耗力&#xff0c;且难以满足居民多样化的需求。近年来&#xff0c;大模型&#xff08;LLMs&#xff09;的崛起为城市规划领域带来了新的机遇。清华大学电子工程系的Zhil…

微信小程序多端框架实现app内自动升级

多端框架生成的app&#xff0c;如果实现app内自动升级&#xff1f; 一、Android 实现app自动升级&#xff0c;华为应用市场 1、获取 应用市场地址 下载地址 2、在微信开放平台进行配置 应用下载地址&#xff1a;应用市场点击分享&#xff0c;里面有一个复制连接功能 应用市…

XMLDecoder反序列化

XMLDecoder反序列化 基础知识 就简单讲讲吧&#xff0c;就是为了解析xml内容的 一般我们的xml都是标签属性这样的写法 比如person对象以xml的形式存储在文件中 在decode反序列化方法后&#xff0c;控制台成功打印出反序列化的对象。 就是可以根据我们的标签识别是什么成分…

QT多媒体编程(一)——音频编程知识详解及MP3音频播放器Demo

目录 引言 一、QtMultimedia模块简介 主要类和功能 二、QtMultimedia相关类及函数解析 QAudioInput QAudioOutput QAudioFormat QMediaPlayer QMediaPlaylist QCamera 三、音频项目实战Demo UI界面 核心代码 运行结果 四、结论 引言 在数字时代&#xff0c;音频…

ArcGIS for js 分屏(vue项目)

一、引入依赖 import {onMounted, ref} from "vue"; import Map from "arcgis/core/Map"; import MapView from "arcgis/core/views/MapView"; import WebTileLayer from "arcgis/core/layers/WebTileLayer"; 二、页面布局 <tem…

22. Hibernate 性能之缓存

1. 前言 本节和大家一起聊聊性能优化方案之&#xff1a;缓存。通过本节学习&#xff0c;你将了解到&#xff1a; 什么是缓存&#xff0c;缓存的作用&#xff1b;HIbernate 中的缓存级别&#xff1b;如何使用缓存。 2. 缓存 2.1 缓存是什么 现实世界里&#xff0c;缓存是一个…

纪念二2024.07 federated-解决mysql跨库联表问题

若需要创建FEDERATED引擎表&#xff0c;则目标端实例要开启FEDERATED引擎。从MySQL5.5开始FEDERATED引擎默认安装 只是没有启用&#xff0c;进入命令行输入 show engines ; FEDERATED行状态为NO。 mysql安装配置文件 一、连接工具查看是否开启federated show engines 二、m…

VMware Workstation17 安装 CentOS7 教程

今天给伙伴们分享一下VMware Workstation17 安装 CentOS7 教程&#xff0c;希望看了有所收获。 我是公众号「想吃西红柿」「云原生运维实战派」作者&#xff0c;对云原生运维感兴趣&#xff0c;也保持时刻学习&#xff0c;后续会分享工作中用到的运维技术&#xff0c;在运维的路…

JS【详解】内存泄漏(含泄漏场景、避免方案、检测方法),垃圾回收 GC (含引用计数、标记清除、标记整理、分代式垃圾回收)

内存泄漏 在执行一个长期运行的应用程序时&#xff0c;应用程序分配的内存没有被释放&#xff0c;导致可用内存逐渐减少&#xff0c;最终可能导致浏览器崩溃或者应用性能严重下降的情况&#xff0c;即 JS 内存泄漏 可能导致内存泄漏的场景 不断创建全局变量未及时清理的闭包&…

Graylog 收集网络设备日志的详细配置指南

需求:网络日志接入到日志服务中,做日志的备份和查询。 交换机或是其它网络设备日志需要接入到graylog日志服务中进行备份和查询。 软件版本 graylog5.1 架构图 一、添加inputs 接受日志信息 二、编辑inputs 配置 第1个红框 title 代表通道的名称,您可以根据需要自由定义…

【CTF-Crypto】格密码基础(例题较多,非常适合入门!)

格密码相关 文章目录 格密码相关格密码基本概念&#xff08;属于后量子密码&#xff09;基础的格运算&#xff08;行列式运算&#xff09;SVP&#xff08;shortest Vector Problem&#xff09;最短向量问题CVP&#xff08;Closet Vector Problem&#xff09;最近向量问题 做题要…

浏览器用户文件夹详解 - ShortCuts(六)

1. Shortcuts简介 1.1 什么是Shortcuts文件&#xff1f; Shortcuts文件是Chromium浏览器中用于存储用户创建的快捷方式信息的一个重要文件。每当用户在浏览器中创建快捷方式时&#xff0c;这些信息都会被记录在Shortcuts文件中。通过这些记录&#xff0c;用户可以方便地快速访…

《小迪安全》学习笔记02

域名默认存放目录和IP默认存放目录不一样。 IP地址是WWW文件里的&#xff0c;域名访问是WWW里的一个子目录里的&#xff08;比如是blog&#xff09;。 Nmap: Web源码拓展 拿到一个网站的源码&#xff0c;要分析这几个方面↑。 不同类型产生的漏洞类型也不一样 在网站中&…

MSPM0G3507_2024电赛自动行驶小车(H题)_问题与感悟

这次电赛题目选的简单了&#xff0c;还规定不能使用到摄像头&#xff0c;这让我之前学习的Opencv 4与树莓派无用武之地了&#xff0c;但我当时对于三子棋题目饶有兴趣&#xff0c;但架不住队友想稳奖&#xff0c;只能选择这个H题了...... 之后我还想抽空将这个E题三子棋题目做…

快手批量取关

目录 突然发现快手木有批量取关功能&#xff0c;没有功能就创造功能 执行代码中 逐渐变少 后面关注列表没人了&#xff0c;总数还有32&#xff0c;不知道是不是帮测出个bug还是咋的(^_^) 突然发现快手木有批量取关功能&#xff0c;没有功能就创造功能 刚开始1000多人 执行代…

中间件之异步通讯组件rocketmq入门

一、概述 1.1介绍 RocketMQ是阿里巴巴2016年MQ中间件&#xff0c;使用Java语言开发&#xff0c;RocketMQ 是一款开源的分布式消息系统&#xff0c;基于高可用分布式集群技术&#xff0c;提供低延时的、高可靠的消息发布与订阅服务。同时&#xff0c;广泛应用于多个领域&#…