当前位置: 首页 > news >正文

【Vue原理】Render - 源码版 之 静态 Render

写文章不容易,点个赞呗兄弟

专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧

研究基于 Vue版本【2.5.17】

如果你觉得排版难看,请点击下面链接或者 拉到 下面关注公众号也可以吧

【Vue原理】Render - 源码版 之 静态 Render

上一篇我们讲了 render 函数,而 Vue 为了更新时速度快一些,加入了一个 staticRender

没错,就是 静态 render,看过前面文章的人,应该知道什么是 静态 render

静态 render 就是用于渲染哪些不会变化的节点

大家可以先看看,Vue 是怎么判断某个节点是否是静态节点

Compile 之 optimize 标记静态节点

好,下面开始我们的正文,想了想,我们还是以几个问题开始吧

1、静态 render 是什么样子的

2、静态 render 是怎么生成和 保存

3、静态 render 怎么执行


什么是 静态Render

静态 render 其实跟 render 是一样的,都是执行得到 Vnode

只是静态 render,没有绑定动态数据而已,也就是说不会变化

比如说,一个简单 render 是这样的

绑定了动态数据,需要从实例去获取

_c('div',[_v(_s(aa))])

而静态 render 是这样的

没有动态数据,这个静态render 的执行结果是永远不会变的

_c('div',[_c('span',[_v("1")])])

生成保存静态Render

静态 render 是在 generate 阶段生成的,生成的方式和 render 是一样的

比如在一个模板中,有很多个静态 根节点,像这样

首先,Vue 会在遍历模板的时候,发现 span 和 strong 本身以及其子节点都是静态的

那么就会给 span 和 strong 节点本身设置一个属性 staticRoot,表示他们是静态根节点

然后这两个静态根节点就会生成自己专属的 静态 render

如何标记静态根节点的具体可以看 Compile 之 optimize 标记静态节点

怎么把静态根节点生成 render 的可以看 Compile 之 generate 节点拼接 中 genStatic 的部分

如果你有一直看我的Vue 笔记的话,你应该这里是会有点印象的

之后

静态 render 生成之后是需要保存的,那么保存在哪里呢?

保存在一个数组中,名叫 staticRenderFns,就是直接push 进去

当然了,此时的 push 进去的 静态 render 还是字符串,并没有变成函数

以上面的模板为例,这里的 staticRenderFns 就是这样,包含了两个字符串

staticRenderFns = [ "_c('span',[_c('b',[_v("1")])])", "_c('strong',[_c('b',[_v("1")])])" ]

但是在后面会逐个遍历变成可执行的函数

staticRenderFns = staticRenderFns.map(code => { return new Function(code) });

那么 这个 staticRenderFns 又是什么啊?

每个 Vue 实例都有一个独立的 staticRenderFns,用来保存实例本身的静态 render

staticRenderFns 的位置是

vm.$options.staticRenderFns


执行静态Render

静态 render 需要配合 render 使用,怎么说

看个例子

这个模板的 render 函数是

_c('div',[ _m(0), _v(_s(a), _m(1) ])

_m(0) , _m(1) 就是执行的就是 静态 render 函数,然后返回 Vnode

于是 render 也可以完成 vnode 树的构建了

那么 _m 是什么呢?

在 Vue 初始化时,给Vue的原型便注册了这个函数,也就是说每个实例都继承到 _m

function installRenderHelpers(target) { target._m = renderStatic; } installRenderHelpers(Vue.prototype);

再来看 renderStatic

function renderStatic(index) { var cached = this._staticTrees || (this._staticTrees = []); var tree = cached[index]; // 如果缓存存在,就直接返回 if (tree) return tree // 这里是执行 render 的地方 tree = cached[index] = this.$options.staticRenderFns[index].call( this, null, this ); // 只是标记静态 和 节点id 而已 markStatic(tree, "__static__" + index, false); return tree }

这个函数做的事情可以分为几件

1、执行静态render

2、缓存静态render 结果

3、标记 静态 render 执行得到的 Vnode

我们来一个个说

1 执行静态render

上面我们说过了,静态render 保存在 数组 staticRenderFns

所以这个函数接收一个索引值,表示要执行数组内哪个静态render

取出静态render 后,执行并绑定 Vue 实例为上下文对象

然后得到 Vnode

2 缓存静态render 结果

这一步就是要把上一步得到的 Vnode 缓存起来

那么缓存在哪里呢?

_staticTrees

这是一个数组,每个实例都会有一个独立的 _staticTrees,用来存在自身的静态 render 执行得到的 Vnode

看一下上个模板中实例保存的 _staticTrees

3 标记 静态 render 执行得到的 Vnode

我们已经执行静态render得到了 Vnode,这一步目的是标记

标记什么呢

1、添加标志位 isStatic

2、添加 Vnode 唯一id

renderStatic 中我们看到标记的时候,调用了 markStatic 方法,现在就来看看

function markStatic( tree, key ) { if (Array.isArray(tree)) { for (var i = 0; i < tree.length; i++) { if ( tree[i] && typeof tree[i] !== 'string') { var node = tree[i] node.isStatic = true; node.key = key + "_" + i; } } } else { tree.isStatic = true; tree.key = key } }
为什么添加标志位 isStatic?

前面我们添加的所有静态标志位都是针对 模板生成的 ast

这里我们是给 Vnode 添加 isStatic,这才能完成Vue的目的

Vue 目的就是性能优化,在页面改变时,能尽量少的更新节点

于是在页面变化时,当 Vue 检测到该 Vnode.isStatic = true,便不会比较这部分内容

从而减少比对时间

Vnode 唯一id

每个静态根Vnode 都会存在的一个属性

我也没想到 静态Vnode 的 key 有什么作用,毕竟不需要比较,也许是易于区分??

最后

静态 render 我们就讲完了,是不是很简单,在没看源码之前,我以为很难

现在看完,发现也简单的,不过我也是看了几个月的。。。。

鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵,如果有任何描述不当的地方,欢迎后台联系本人,有重谢

http://www.jsqmd.com/news/1280986/

相关文章:

  • RSS技术生态解析:从传统到现代的演进与实践
  • 荣耀将阿莱电影工作流融入机器人手机
  • 求k阶斐波那契第m项的值
  • 2026指南:成都净味环保科技有限公司——新房除味道服务品牌机构实力解析 - 卓企推荐
  • NBM7100A与PIC18LF4620在低功耗物联网设备中的应用
  • 物联网设备硬件级安全防护:SE050与PIC18F实战指南
  • 物联网设备安全芯片SE050与TM4C1294集成方案详解
  • 物联网设备硬件安全方案与SE050开发实践
  • 【JAVA课程设计/毕业设计】基于物联网的仓储物资智能化管理系统 基于 SpringBoot+Vue 的智能仓储环境感知与物资调度管理平台【附源码、数据库、万字文档】
  • 从零打造遥控氦气球:浮力、动力与控制的轻量化工程实践
  • TPIC7710EVM评估模块:汽车电子ASIC功能验证与系统集成实战指南
  • 089、YOLOv8改进实战:IoU损失函数演进全解——从GIoU到Shape-IoU的数学本质与代码实现
  • Linux 内核调优选型对比:BBR vs cubic、swappiness 三档策略与大页内存的适用场景
  • 权限和日志失效后,测试工程师如何证明大模型价值?
  • 输出链表倒数节点
  • 兴趣电商内容策略:从算法逻辑到品牌实践
  • 动态规划背包问题
  • Godot引擎集成AI代码生成:加速游戏原型开发实践
  • 超声波焊接机市场格局解析:国际一线品牌与国产技术中坚如何选择? - 品牌推荐大师
  • ABAQUS盾构隧道下穿施工模拟技术与工程实践
  • Hashcat实战:五种方法破解NTLM哈希与掩码规则速查
  • AI降噪工具千笔:专业降低AI生成内容机械感
  • Unity光照Shader实战:从Blinn-Phong原理到URP自定义实现与优化
  • HF Patch:一键解锁《恋活!》200+插件,打造终极游戏体验
  • 职场周报撰写指南:结构、技巧与优化建议
  • Windows电脑运行安卓应用:终极APK安装器完整使用指南
  • ComfyUI-WanVideoWrapper:AI视频生成从入门到精通,3天变3分钟
  • 完全掌握抖音下载神器:douyin-downloader 从入门到精通实战指南
  • C++ ~ 类的声明和类的实现分开
  • 如何10分钟制作专业短视频?MoneyPrinterTurbo的AI视频创作终极指南 [特殊字符]