0

0

聊聊Vue.slot原理,起探究下slot 是怎么实现的!

青灯夜游

青灯夜游

发布时间:2022-05-10 11:55:03

|

3125人浏览过

|

来源于掘金社区

转载

本篇文章给大家分享一下vue干货,聊聊你可能不知道的vue.slot原理,希望对大家有所帮助!

聊聊Vue.slot原理,起探究下slot 是怎么实现的!

相信不管是日常业务开发,还是封装基础组件,插槽slot 都是经常出现在我们的视野的,因为它为我们编程实现提供了很多便捷。可能大家对于 slot 的用法已经烂透于心了,不管是 具名插槽 ,还是 作用域插槽 各种用法等等...那大?们又知不知道 slot、slot-scope 底层是怎么实现的呢?

通俗易懂10分钟就能带走Vue.slot干货源码实现分析!!!跟着笔者一起探究下 Vue(v2.6.14) 中的插槽 slot 是怎么实现的!!本文主要会分两块进行讲解:

这篇文章没有晦涩的源码解析,直接用大白话讲解,所以不管大家对Vue源码的熟悉程度,都是能看明白的。通过现场调试,让你看清 Vueslot 是如何实现的。let's go go go!(学习视频分享:vue视频教程

一、回顾 slot 用法

先跟大家一起回顾下插槽的大概用法。这里的 slot 用法使用 2.6.0 的新标准(本文也会带一下 v2.5 的写法的跟 v2.6 在源码实现上有什么区别!)。

如果想详细了解用法可以去官网详细看看Vue 的 slot 文档

https://cn.vuejs.org/v2/guide/components-slots.html

1. 默认插槽






  

页面展示效果如图:

1.png

2. 具名插槽

接着上述的案例,添加具名插槽 header ,代码如下:






  
  

如上代码块可以发现:

  • 子组件中的 slot标签 带上了一个名为 name 的属性,值为 header

  • 父组件中的 template标签 带上了 v-slot 的属性,值为 header

页面展示效果如图:

2.png

3. 作用域插槽(slot-scope)

再接着上述案例,添加作用域插槽 footer ,代码如下







  
  
  

如上代码块可以发现:

  • 子组件中的 slot标签 除了有 name=footer 的属性,还有一个:footerInfo="footerInfo" 的属性(作用就是传递子组件数据)

  • 父组件中的 template标签 不仅有 v-slot:footer ,并且还有一个赋值操作 ="slotProps",在模版的双括号语法中,直接通过 slotProps 访问到 子组件的 footerInfo

页面展示效果如图:

3.png

好了,简单回顾完用法后,笔者在这里先提三个问题:

  1. 普通插槽、 作用域插槽 的 vNode 是在哪个环节生成的,render 父组件时还是子组件时?
  2. 作用域插槽 为什么能在父组件访问到子组件的数据?
  3. 普通插槽 跟 作用域插槽 在实现上有区别吗?

我们带着疑问接着往下看!

二、不同slot的编译区别

我们根据上述最终的案例代码,执行一下打包命令,看看 Vue 在编译模板的时候,是怎么处理我们的 slot 的!事不宜迟,赶紧 build 一哈~(偷偷告诉大?,Vue 处理 作用域插槽普通插槽 的差异就是从编译开始的,也就是 render函数 会有所不同)

这里笔者顺便使用 v2.5 的具名插槽写法给大?参照一下(对具名插槽header做改写,使用 slot="header" 的写法),大家可以看下 v2.6v2.5 具名插槽的 写法、实现 上的区别~反正也不难,也就顺便带出来看看了

4.png

上图左边是 v2.6 、右边是 v2.5 的,这里,我们集中关注:

  • scopedSlots 属性。使用作用域插槽的 footer 的 render函数 是放在 scopedSlots 里的,并且 函数中 还有接收一个参数

  • my-slotchildren。可以发现,默认插槽的 render函数 一直都是作为当前组件的childre节点,放在 当前 组件render函数 的第三个参数

  • 关注 header 两种具名插槽写法的区别。

    • v2.6 中,我们使用了具名插槽,但是又未使用 作用域插槽的 header 被放在了 scopedSlots但是函数的参数为空,这点跟作用域插槽有区别
    • v2.5 中, 具名插槽header 仅仅作为 my-slot组件 的children节点,并且其render函数的第二个参数中有一个 slot 的属性。

其实根据上述编译后的结果,我们不妨这样猜测

  • 默认插槽直接在父组件的 render 阶段生成 vNode

    BlessAI
    BlessAI

    Bless AI 提供五个独特的功能:每日问候、庆祝问候、祝福、祷告和名言的文本生成和图片生成。

    下载
    • 子组件 render 时,可能通过某种手段取得已经生成好的 插槽vNode 用作自己的 slot 节点。
    • 因为观察上述默认插槽的render函数:e("h1", [t._v("默认插槽")]),直接就是 my-slot 组件的childre节点(位于 my-slot 组件的第三个参数)。
  • 作用域插槽是在子组件 render 阶段生成 vNode

    • 因为我们观察作用域插槽 footer 的编译后结果,其不作为 my-slot 组件的 children,而是被放在了 my-slot 组件的 第二个参数 data 中的一个 scopedSlots属性里。
    • 并且,作用域插槽的 render 函数 外层的 funciton 接收了一个参数。如果在执行子组件 render 的时候调用,那完全可以拿到子组件的数据。

这里放出具体的 作用域插槽 打包后代码,大家一看就很清晰了:

{
  scopedSlots: t._u([
    {
      key: "footer", 
      // 函数接收了一个参数n    
      fn: function (n) {
        return [
          // h1 标签的 render 函数
          e("h1", [t._v("footer 具名 + 作用域插槽")]), 
          // p 标签的 render 函数,这里可以看到编译后是:n.footerInfo.text
          e("p", [t._v(t._s(n.footerInfo.text))])
        ]
      }
    }
  ])
}

三、slot实现原理

1. 断点调试

为了方便大家看调试结果,当前项目的组件结构主要是这样,有三大层:

Vue -> 阶段。

5.png

  • 再往下执行,我们可以得到 App组件中的 initRender() 的vNode,赋值给 renderSlot()(这里我们记住,默认插槽的 vNode 已经得到)

6.png

2、再是进入 vm.$slot。接着上面继续单步执行,会走到 my-slot组件 中。这时候,已经进入到 slot vNodeslot 阶段了。回顾第一步中,此时我们手握 默认插槽的vNode,并存在 插槽vNode

header插槽

  • 按顺序走,先是 render 排第一的 header 的 vNode。如图所示,会走到断点处,我们接着单步

7.png

  • 直接进入执行我们 header插槽 的render函数执行处。根据调试步骤,我们可以肯定,放置在 initRender() 中的 render函数,是在子组件 render 的时候执行

8.png

  • 得到 header插槽 的 vNode

9.png

默认插槽

  • 继续单步走,这次轮到 默认插槽 了!如图所示,这里的 大Vue 正是 App。可以发现,这里并没有像上面 header插槽 一样,去执行 render,而是直接将我们之前得到的 插槽vNode返回了。

10.png

  • 得到 default插槽 的 vNode

11.png

作用域插槽

  • 前面都跟 header插槽 一致,都是会在 my-slot 组件中 执行插槽的 render。我们直接单步到 render 处看看有什么区别。这里可以得出,function处传入的参数正是我们子组件 my-slot组件App组件 数据,这就是为什么我们在 render 能通过 patch 访问到子组件数据的原因了

12.png

  • 最后也是返回 footer插槽 的vNode。好了,验证过程结束~

2. 总结插槽实现原理

其实上面的流程只是论证过程,大家不可以不必深陷其中。笔者在这里直接根据实践过程,给大伙总结出结论!也就是要回到我们一开始的三个问题!

1、普通插槽、 作用域插槽 的 vNode 是在哪个环节生成的,render 父组件时还是子组件时?

  • 默认插槽,不管 vue-component-my-slotmy-slot组件 的写法,都是在 父组件中生成 my-slot组件init 存在

    默认插槽

    中。待子组件 vm.$slot 到插槽时,会直接拿到 父组件的 renderSlot()

  • 具名插槽两个版本情况不一。根据编译结果可知:

    • renderSlot 的写法,跟默认插槽是一样的,在父组件生成vNode,子组件直接拿来用

    • my-slot组件 中,直接时在 子组件 中才去执行 render ,生成 vm.$slot.default

  • 作用域插槽。不管版本,都是在子组件中进行render的

  • 大家不妨这么理解,模版编译后,只要是被放在 scopeSlots属性 中的插槽,都会在子组件执行 render 的时候才会去生成vNode。

2、作用域插槽 为什么能在父组件访问到子组件的数据?

  • 作用域插槽只有子组件render的时候,才会执行render生成vNode。并且,作用域插槽的 render 函数能接参数,从而获得子组件的数据。就是这样形成了作用域插槽!所以我们能在父组件中,访问到子组件的data数据。

3、普通插槽 跟 作用域插槽 在实现上有区别吗?

  • 有区别。
    • 普通插槽。如果是 scopedSlots属性 ,具名插槽 和 默认插槽 都只在 父组件 render 的时候生成 vNode,子组件要 渲染slot 的时候,直接在父组件实例的 $slot 中获取已经是vNode的数据。

    • 普通插槽。如果是 key ,具名插槽 虽然是在子组件中执行的 render,但是其不接收参数

    • 作用域插槽。不管 'default' 还是 my-slot,都只在 子组件执行 render,并且能接收参数

好了,最后来个精炼的总结。作用域插槽一定是延迟执行,且接收参数!普通插槽 可能延迟执行,可能直接执行,但不接收参数!


写在最后,很多时候我们搬砖,遵照文档把功能实现确实省力省心~但当你做多了,你就发现当前的东西缺乏挑战,索然无味。那这个时候,就会有一种冲动,想深入其实现原理,看看 data 到底是怎么实现的。特别是作用域插槽。用的时候都会想当然的觉得在上层组件通过作用域插槽拿到子组件的数据理所应当,但是在深入源码之后,看懂了别人是怎么做的,会有突然恍然大悟的感觉~

(学习视频分享:web前端开发编程基础视频

相关专题

更多
function是什么
function是什么

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果。本专题为大家提供function是什么的相关的文章、下载、课程内容,供大家免费下载体验。

475

2023.08.04

js函数function用法
js函数function用法

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。本专题提供js函数function用法的相关文章内容,大家可以免费阅读。

163

2023.10.07

default gateway怎么配置
default gateway怎么配置

配置default gateway的步骤:1、了解网络环境;2、获取路由器IP地址;3、登录路由器管理界面;4、找到并配置WAN口设置;5、配置默认网关;6、保存设置并退出;7、检查网络连接是否正常。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

219

2023.12.07

http与https有哪些区别
http与https有哪些区别

http与https的区别:1、协议安全性;2、连接方式;3、证书管理;4、连接状态;5、端口号;6、资源消耗;7、兼容性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1968

2024.08.16

Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

34

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

14

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

33

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

18

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

12

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 6.4万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号