写文章不容易点个赞呗兄弟专注 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用来保存实例本身的静态 renderstaticRenderFns 的位置是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的原型便注册了这个函数也就是说每个实例都继承到 _mfunction installRenderHelpers(target) { target._m renderStatic; } installRenderHelpers(Vue.prototype);再来看 renderStaticfunction 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、执行静态render2、缓存静态render 结果3、标记 静态 render 执行得到的 Vnode我们来一个个说1 执行静态render上面我们说过了静态render 保存在 数组 staticRenderFns所以这个函数接收一个索引值表示要执行数组内哪个静态render取出静态render 后执行并绑定 Vue 实例为上下文对象然后得到 Vnode2 缓存静态render 结果这一步就是要把上一步得到的 Vnode 缓存起来那么缓存在哪里呢_staticTrees这是一个数组每个实例都会有一个独立的 _staticTrees用来存在自身的静态 render 执行得到的 Vnode看一下上个模板中实例保存的 _staticTrees3 标记 静态 render 执行得到的 Vnode我们已经执行静态render得到了 Vnode这一步目的是标记标记什么呢1、添加标志位 isStatic2、添加 Vnode 唯一idrenderStatic 中我们看到标记的时候调用了 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 我们就讲完了是不是很简单在没看源码之前我以为很难现在看完发现也简单的不过我也是看了几个月的。。。。鉴于本人能力有限难免会有疏漏错误的地方请大家多多包涵如果有任何描述不当的地方欢迎后台联系本人有重谢