Vue 2阅读理解之initRender与callHook组件详解
initRender 组件渲染初始化
在 initEvents 事件系统初始化完成之后,紧接着的就是组件实例的渲染部分的初始化 initRender。
initRender 函数定义位于 src/core/instance/render.ts 文件内,基本定义如下:
export function initRender(vm: Component) { vm._vnode = null vm._staticTrees = null const options = vm.$options const parentVnode = (vm.$vnode = options._parentVnode!) const renderContext = parentVnode && (parentVnode.context as Component) vm.$slots = resolveSlots(options._renderChildren, renderContext) vm.$scopedSlots = parentVnode ? normalizeScopedSlots(vm.$parent!, parentVnode.data!.scopedSlots, vm.$slots) : emptyObject vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false) vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true) const parentData = parentVnode && parentVnode.data if (__DEV__) { defineReactive( vm, '$attrs', (parentData && parentData.attrs) || emptyObject, () => !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm), true ) defineReactive( vm, '$listeners', options._parentListeners || emptyObject, () => !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm), true ) } else { // 将 defineReactive 的第四个参数设为 null 重新执行上面的步骤,即省略校验和报错部分 } }
这部分其实比较好理解:
首先是 清空 组件的 VNode 对象和静态dom节点树;并获取到该实例的 父组件虚拟dom树对象 parentVnode 与 父组件实例指向 renderContext
然后是处理 当前组件的 slots 插槽对象 ,以及标准化处理组件的数据域插槽
给组件添加两个 组件创建方法,但是这两个方法有细微差别:
- _c 表示使用内部 render 函数,不需要额外的标准化处理
- $createElement 则表示使用的是用户自己编写的 render 函数,需要内部重新进行一次标准化处理
- 这两个方法最终其实都是调用的 _createElement 方法,只是标准函数(即 _c)使用 simpleNormalizeChildren() 处理,而用户自定义 render (即 $createElement)使用 normalizeChildren() 处理
最后对 attrs∗∗和∗∗attrs** 和 **attrs∗∗和∗∗listeners 进行响应式处理。这一步主要是为了提供给高阶组件使用,当使用 attrs∗∗和∗∗attrs** 和 **attrs∗∗和∗∗listeners 进行绑定数据与事件透传时,可以正确触发高阶组件内部的状态更新。
整个过程其实就是解析了组件的 options 配置项与父组件的绑定参数,并对插槽和数据域插槽进行不同处理,最后给组件添加 _createElement 的事件指向绑定,并响应式处理两个组件内部没有直接定义的参数/事件。
callHook('beforeCreate')
因为这部分篇幅较少,所以把 callHook() 方法也一并看了。
这个方法从名字上就可以看出,是用来触发生命周期钩子的回调函数。在之前的 mergeOptions 配置合并 中已经知道,Vue 组件在实例化的时候会对 options 中的生命周期钩子函数定义进行标准化处理,最后每个生命周期对应的都是一个 函数数组(如果有定义了钩子函数的话)。
该方法的定义如下:
export function callHook(vm: Component, hook: string, args?: any[], setContext = true) { pushTarget() const prev = currentInstance setContext && setCurrentInstance(vm) const handlers = vm.$options[hook] const info = `${hook} hook` if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { invokeWithErrorHandling(handlers[i], vm, args || null, vm, info) } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } setContext && setCurrentInstance(prev) popTarget() }
这里可以分成一下几步来理解:
- pushTarget() :在组件的 Dep 依赖中插入一个 undefined 元素并将当前依赖指向设置为 undefined,来禁止生命周期钩子函数执行时的依赖收集
- 遍历 options 中对应的钩子函数数组,调用 invokeWithErrorHandling 来执行(这里其实与 initEvnets 中注册组件事件的方法是一致的)
- 如果 _hasHookEvent 为 true,即父组件有设置子组件的生命周期监听函数,则用 $emit 抛出对应生命周期事件
- popTarget() :删除之前插入的 undefined 元素,并恢复 Dep 依赖对象中的依赖收集效果
- 两个 setCurrentInstance:这部分则是为了适配 V3 的写法而新增的部分,主要是保证在生命周期的钩子函数中使用 getCurrentInstance() 方法获取当前组件实例时能正确获取到当前的组件状态,但是在钩子函数执行完之后会恢复到之前的状态
以上就是Vue 2阅读理解之initRender与callHook组件详解的详细内容,更多关于Vue2 组件initRender callHook的资料请关注猪先飞其它相关文章!
原文出处:https://juejin.cn/post/7135007624793161759
相关文章
- 这篇文章主要介绍了vue中activated的用法,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2021-01-03
基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能
这篇文章主要介绍了基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-23Antd-vue Table组件添加Click事件,实现点击某行数据教程
这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17- 这篇文章主要介绍了vue 实现动态路由的方法,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-06
- 这篇文章主要介绍了Vue组件跨层级获取组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-28
- 这篇文章主要介绍了Vue基于localStorage存储信息代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-16
antdesign-vue结合sortablejs实现两个table相互拖拽排序功能
这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-09- 这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
- 这篇文章主要介绍了vue 监听 Treeselect 选择项的改变操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
- 最常见的多环境配置,就是开发环境配置,和生产环境配置,本文主要介绍了vue项目多环境配置的实现,感兴趣的可以了解一下...2021-07-20
- 这篇文章主要介绍了Vue 3.0 中 jsx 语法使用,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2020-11-13
vue项目页面嵌入代码块vue-prism-editor的实现
这篇文章主要介绍了vue项目页面嵌入代码块vue-prism-editor的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-30解决vue的router组件component在import时不能使用变量问题
这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27vue Treeselect下拉树只能选择第N级元素实现代码
这篇文章主要介绍了vue Treeselect下拉树只能选择第N级元素实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01- 这篇文章主要为大家详细介绍了vue实现同时设置多个倒计时,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-05-20
Ant design vue table 单击行选中 勾选checkbox教程
这篇文章主要介绍了Ant design vue table 单击行选中 勾选checkbox教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-25- 这篇文章主要介绍了Vue select 绑定动态变量的实例讲解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-23
- 这篇文章主要为大家详细介绍了vue实现div单选多选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-16
- 这篇文章主要介绍了vue treeselect获取当前选中项的label实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
vuejs element table 表格添加行,修改,单独删除行,批量删除行操作
这篇文章主要介绍了vuejs element table 表格添加行,修改,单独删除行,批量删除行操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18