Vue 2阅读理解之initRender与callHook组件详解

 更新时间:2022年08月24日 15:23:32   作者:MiyueFE  
这篇文章主要为大家介绍了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 中注册组件事件的方法是一致的)
  • 如果 _hasHookEventtrue,即父组件有设置子组件的生命周期监听函数,则用 $emit 抛出对应生命周期事件
  • popTarget() :删除之前插入的 undefined 元素,并恢复 Dep 依赖对象中的依赖收集效果
  • 两个 setCurrentInstance:这部分则是为了适配 V3 的写法而新增的部分,主要是保证在生命周期的钩子函数中使用 getCurrentInstance() 方法获取当前组件实例时能正确获取到当前的组件状态,但是在钩子函数执行完之后会恢复到之前的状态

以上就是Vue 2阅读理解之initRender与callHook组件详解的详细内容,更多关于Vue2 组件initRender callHook的资料请关注脚本之家其它相关文章!

相关文章

  • vant 时间选择器--开始时间和结束时间实例

    vant 时间选择器--开始时间和结束时间实例

    这篇文章主要介绍了vant 时间选择器--开始时间和结束时间实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Vue中两种生成二维码(带logo)并下载方式总结

    Vue中两种生成二维码(带logo)并下载方式总结

    与后端生成二维码相比,前端生成二维码更具有灵活性,下面这篇文章主要给大家介绍了关于Vue中两种生成二维码(带logo)并下载的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • Element el-button 按钮组件的使用详解

    Element el-button 按钮组件的使用详解

    这篇文章主要介绍了Element el-button 按钮组件的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • 简述vue状态管理模式之vuex

    简述vue状态管理模式之vuex

    这篇文章主要介绍了简述vue状态管理模式之vuex,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • Vue监听页面变化的实现方法小结

    Vue监听页面变化的实现方法小结

    在Vue.js应用开发过程中,监听页面变化是一个非常常见的需求,无论是为了响应用户交互、优化性能,还是实现复杂的业务逻辑,监听页面变化的能力都是不可或缺的,本文将详细介绍如何在Vue项目中实现页面变化监听,需要的朋友可以参考下
    2024-10-10
  • vue项目使用定时器每隔几秒运行一次某方法代码实例

    vue项目使用定时器每隔几秒运行一次某方法代码实例

    有时候在项目中我们经常需要设置简单的倒计时功能,这个可以通过定时器来实现,下面这篇文章主要给大家介绍了关于vue项目使用定时器每隔几秒运行一次某方法的相关资料,需要的朋友可以参考下
    2023-04-04
  • Vue倒计时3秒后返回首页Demo(推荐)

    Vue倒计时3秒后返回首页Demo(推荐)

    这篇文章主要介绍了Vue倒计时3秒后返回首页Demo,倒计时结束后要清除计时器,防止内存泄漏,本文通过示例代码给大家介绍的非常详细,需要的朋友参考下吧
    2023-11-11
  • html中引入Vue.js的cdn实现简单的文档单页

    html中引入Vue.js的cdn实现简单的文档单页

    这篇文章主要为大家介绍了html中引入Vue.js的cdn实现简单的文档单页示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • 封装一个更易用的Dialog组件过程详解

    封装一个更易用的Dialog组件过程详解

    这篇文章主要为大家介绍了封装一个更易用的Dialog组件过程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Vue学习笔记之表单输入控件绑定

    Vue学习笔记之表单输入控件绑定

    本篇文章主要介绍了Vue学习笔记之表单输入绑定,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09

最新评论