2025年vue插槽的原理(vue3.0 插槽)

vue插槽的原理(vue3.0 插槽)Vue 实现了一套内容分发的 API 这套 API 的设计灵感源自 nbsp Web Components 规范草案 将 nbsp nbsp 素作为承载分发内容的出口 那么 Slot 到底是什么呢 Slot 其实是一个接受父组件传过来的插槽内容 然后生成 VNode 并返回的函数 我们一般是使用 这对标签进行接受父组件传过来的内容 那么这对标签最终编译之后是一个创建 VNode 的函数 我们可以叫做创建插槽 VNode 的函数 我们可以清楚看到标签被 Vue3 编译之后的就变成了一个叫的函数



Vue 实现了一套内容分发的 API,这套 API 的设计灵感源自 Web Components 规范草案,将  元素作为承载分发内容的出口。

那么Slot到底是什么呢?Slot其实是一个接受父组件传过来的插槽内容,然后生成VNode并返回的函数。

我们一般是使用 这对标签进行接受父组件传过来的内容,那么这对标签最终编译之后是一个创建VNode的函数,我们可以叫做创建插槽VNode的函数。

我们可以清楚看到标签被Vue3编译之后的就变成了一个叫的函数。

要使用插槽那就必须存在父子组件。

假设父组件为一下内容:

我们在父组件使用了一个的子组件,并且传递了的插槽内容。

todo-button子组件模版内容

当组件渲染的时候, 将会被替换为“Add todo”。

那么这其中底层的原理是什么呢?在理解插槽的底层原理之前,我们还需要回顾一下Vue3的组件运行原理。

组件的核心是它能够产出一坨VNode。对于 Vue 来说一个组件的核心就是它的渲染函数,组件的挂载本质就是执行渲染函数并得到要渲染的VNode,至于什么data/props/computed 这都是为渲染函数产出 VNode 过程中提供数据来源服务的,最关键的就是组件最终产出的VNode,因为这个才是需要渲染的内容。

Vue3在渲染VNode的时候,发现VNode的类型是组件类型的时候,就会去走组件渲染的流程。组件渲染的流程就是首先创建组件实例,然后初始化组件实例,在初始化组件实例的时候就会去处理Slot相关的内容。

在源码的runtime-coresrccomponent.ts里面

在函数initSlots里面初始化组件Slot的相关内容

那么initSlots函数长啥样,都干了些什么呢?

runtime-coresrccomponentSlots.ts

首先要判断该组件是不是Slot组件,那么怎么判断该组件是不是Slot组件呢?我们先要回去看一下上面父组件编译之后的代码:

我们可以看到Slot组件的children内容是一个Object类型,也就是下面这段代码:

那么在创建这个组件的VNode的时候,就会去判断它的children是不是Object类型,如果是Object类型那么就往该组件的VNode的shapeFlag上挂上一个Slot组件的标记。

如果是通过模板编译过来的那么就是标准的插槽children,是带有属性的,是可以直接放在组件实例上的属性。

如果是用户自己写的插槽对象,那么就没有属性,那么就需要进行规范化处理,走 。

如果用户搞骚操作不按规范走,那么就走流程。

我们先看看子组件编译之后的代码:

上面我们也讲过了标签被vue3编译之后的就变成了一个叫的函数。

函数接受五个参数,第一个是实例上的插槽函数对象,第二个是插槽的名字,也就是将插槽内容渲染到指定位置 ,第三个是插槽作用域接收的,第四个是插槽的默认内容渲染函数,第五个暂不太清楚什么意思。

作用域插槽是一种子组件传父组件的传参的方式,让插槽内容能够访问子组件中才有的数据 。

子组件模板

编译后的代码

父组件模板

编译后的代码

上面讲过renderSlot函数,可以简单概括成下面的代码

是组件实例上传过来的插槽内容,其实就是这段内容

name是default,那么slots[name]得到的就是下面这个函数

slot(props)就很明显是slot({ username: "coboy" }),这样就把子组件内的数据传到父组件的插槽内容中了。

有时我们需要多个插槽。例如对于一个带有如下模板的  组件:

对于这样的情况, 元素有一个特殊的 attribute:。通过它可以为不同的插槽分配独立的 ID,也就能够以此来决定内容应该渲染到什么地方:

一个不带  的  出口会带有隐含的名字“default”。

在向具名插槽提供内容的时候,我们可以在一个  元素上使用  指令,并以  的参数的形式提供其名称:

父组件编译之后的内容:

子组件编译之后的内容:

通过子组件编译之后的内容我们可以看到这三个Slot渲染函数

_renderSlot(_ctx.$slots, "header")

_renderSlot(_ctx.$slots, "default")

_renderSlot(_ctx.$slots, "footer")

然后我们再回顾一下renderSlot渲染函数

这个时候我们就可以很清楚的知道所谓具名函数是通过renderSlots渲染函数的第二参数去定位要渲染的父组件提供的插槽内容。父组件的插槽内容编译之后变成了一个Object的数据类型。

我们可能希望这个  内绝大多数情况下都渲染“Submit”文本。为了将“Submit”作为备用内容,我们可以将它放在  标签内

现在当我们在一个父级组件中使用  并且不提供任何插槽内容时:

备用内容“Submit”将会被渲染:

但是如果我们提供内容:

则这个提供的内容将会被渲染从而取代备用内容:

这其中的原理是什么呢?我们先来看看上面默认内容插槽编译之后的代码

我们可以看到插槽函数的内容是这样的

我们再回顾看一下renderSlot函数

函数接受五个参数,第四个是插槽的默认内容渲染函数。

再通过renderSlot函数的源码我们可以看到,

第一步,先获取父组件提供的内容插槽的内容,

第二步,如果父组件有提供插槽内容则使用父组件提供的内容插槽,没有则执行默认内容渲染函数得到默认内容。

以上就是Vue3插槽Slot实现原理详解的详细内容,更多关于Vue3插槽Slot的资料请关注脚本之家其它相关文章!

编程小号
上一篇 2025-02-23 12:57
下一篇 2025-02-24 13:01

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/23851.html