背景
摸鱼的时候看到有网友说面试问到了render函数和beforeMount钩子哪个先触发的问题,我印象中是先触发beforeMount钩子,不过本着严谨的精神,拒绝印象流,还是去翻了一下Vue2源码。
想知道结论可以直接跳到文章末尾。
解析
从$mount方法开始
$mount 方法,也就是Vue挂载的起点。
这里可以看到, $mount 方法其实就是调用 mountCompenent 并返回执行结果
mountCompenent发生了什么?
这里截取关键部分
在这里已经有结论了,beforeMount是在render函数调用之前触发的,不过出于好奇,还是去第七行的 _render 函数里面看看细节
render函数的调用细节
转到 _render 中
可以看到 _render 就是调用 render 函数并返回 vnode。不过在第10行可以发现,调用 render 函数的方式并不是直接调用,而是通过call方法,第一个参数是 render 函数的this环境,第二个参数就是在 render 函数中的参数 h 。
第一个参数:vm._renderProxy
从上一部分得知, vm._renderProxy 就是 render 函数的this环境,转到相应源码看看。
可以看到, vm._renderProxy 要么是 vm 本身,要么是 vm 的一个Proxy,据Proxy API的支持情况而定。如果是后者,情况就复杂一些:如果 options.render._withStripped 为真,则Proxy的handler为 getHandler_1 ,否则是 hasHandler_1 。可是这个 options.render._withStripped 并没有在Vue源码中出现,最后在负责编译sfc的 compiler-sfc.js 中找到了。
// compiler-sfc.js // mark with stripped (this enables Vue to use correct runtime proxy // detection) code += `render._withStripped = true`;
变量code就是sfc编译后的js代码,也就是说如果是sfc就是 getHandler_1 ,否则就是 hasHandler_1 ,以上这两个handler的代码就不贴了,不然又是一个新坑=.=
总而言之,这个 vm._renderProxy 就是 vm ,只不过通过Proxy做了一些特殊处理。
第二个参数:vm.$createElement
读过snabbdom的应该都认识这个函数,毕竟vue借鉴了snabbdom。源码太长就不贴了,只要知道它最终调用 _createElement 返回vnode就行。
结论
render 函数的调用时机是在 beforeMount 之后和 mounted 之前。 通过call将 render 函数的this绑定到了vm,并且会根据Proxy的支持情况和是否是SFC来做一些不同的处理。 render 函数的参数 h 的作用是创建vnode以上就是Vue中render函数调用时机与执行细节源码分析的详细内容,更多关于Vue render函数调用执行的资料请关注其它相关文章!
查看更多关于Vue中render函数调用时机与执行细节源码分析的详细内容...