面试时这样回答Vue生命周期,面试官说:你明天直接来上班!!!

面试

面试前端时,我们经常会被问到:你能讲一下vue的生命周期吗?

你可能会这么说:vue的生命周期有beforeCreate、created、beforeMount、mounted......

面试官可能会告诉你:可以了,回去等面试结果通知吧!!!

如果这时你还能讲一讲vue生命周期的执行原理,这岂不是能在面试中有所加分,不然,你拿什么与别人与众不同

要想深入了解vue的生命周期,首先让我们看到vue源码

Vue生命周期源码解析

callHook函数

在vue源码lifecycle.ts文件下有这么一个方法:

scss 复制代码
//lifecycle.ts
export function callHook(
  vm: Component,
  hook: string,
  args?: any[],
  setContext = true
) {
  // #7573 disable dep collection when invoking lifecycle hooks
  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()
}

这个方法被多处引入使用

_init方法中:

mountComponent方法中:

callUpdatedHooks方法中:

$destroy方法中:

其实这些callHook方法都是在执行相应的生命周期钩子函数,即:执行所提供的生命周期回调函数

callHook函数形参:

vm:Component(当前组件实例对象)

hook:string(生命周期名,如:"beforeCreate","created","beforeMount","mounted"......)

args:any[](执行生命周期钩子函数时,传递的参数)

setContext:Boolean(默认为true,为真时设置currentInstance为vm实例对象,为假时不进行此操作)

callHook函数是如何获取并执行生命周期钩子函数的?

回到callHook函数中,const handlers = vm.$options[hook]handlers变量(存储着对应生命周期钩子函数的数组)

继续往下

typescript 复制代码
//lifecycle.ts
//callHook函数中
if (handlers) {
  for (let i = 0, j = handlers.length; i < j; i++) {
    invokeWithErrorHandling(handlers[i], vm, args || null, vm, info)
  }
}
​
​
//error.ts
export function invokeWithErrorHandling(
  handler: Function,
  context: any,
  args: null | any[],
  vm: any,
  info: string
) {
  let res
  try {
    res = args ? handler.apply(context, args) : handler.call(context)
    if (res && !res._isVue && isPromise(res) && !(res as any)._handled) {
      res.catch(e => handleError(e, vm, info + ` (Promise/async)`))
      // issue #9511
      // avoid catch triggering multiple times when nested calls
      ;(res as any)._handled = true
    }
  } catch (e: any) {
    handleError(e, vm, info)
  }
  return res
}

callHook 函数中遍历handlers (生命周期钩子函数数组),遍历至每一项时会执行函数:invokeWithErrorHandling(handlers[i], vm, args || null, vm, info)

handlers[i]为生命周期钩子函数

vm为当前组件实例对象

args为传递给钩子函数的参数

info为string:"生命周期名 hook"

然后,通过invokeWithErrorHandling 函数中res = args ? handler.apply(context, args) : handler.call(context) 执行相应生命周期钩子函数

handlers生命周期钩子函数为何是数组?

handlers中包含通过minxin混入的生命周期钩子函数和组件的生命周期钩子函数,所以它是一个数组 ,handlers[]:Function

vm.$options[hook]是在何时初始化生命周期钩子函数的?

_init函数中:

swift 复制代码
//init.ts
//Vue.prototype._init中
   if (options && options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options as any)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor as any),
        options || {},
        vm
      )
    }

如果当前初始化是new Vue实例,会执行*vm. <math xmlns="http://www.w3.org/1998/Math/MathML"> o p t i o n s = m e r g e O p t i o n s ( r e s o l v e C o n s t r u c t o r O p t i o n s ( v m . c o n s t r u c t o r a s a n y ) , o p t i o n s ∣ ∣ , v m ) ∗ ,并且生命周期钩子函数数组挂载在 v m . options = mergeOptions(resolveConstructorOptions(vm.constructor as any),options || {},vm)* ,并且生命周期钩子函数数组挂载在vm. </math>options=mergeOptions(resolveConstructorOptions(vm.constructorasany),options∣∣,vm)∗,并且生命周期钩子函数数组挂载在vm.options上

如果是子组件初始化,会执行initInternalComponent(vm, options as any) ,并且生命周期钩子函数数组会挂载在vm.$options原型链上

vue组件@hook:xxx事件

callHook 函数在执行完生命周期钩子函数(invokeWithErrorHandling)后会执行hook:xxx事件

bash 复制代码
//lifecycle.ts
//callHook函数中
if (vm._hasHookEvent) {
    vm.$emit('hook:' + hook)
}

例如我们要在父组件中监听子组件mounted钩子函数执行完,我们可以这样做:

1、子组件与父组件通过on与emit进行发布订阅

2、在子组件上注册hook:xxx事件:<compontent @hook:mounted="action" />,action事件会在执行完mounted生命周期钩子函数后被调用

如果觉得内容对你有帮助或者有所成长,麻烦请点个小小的赞加收藏,谢谢。^o^

相关推荐
come1123413 分钟前
Vue 响应式数据传递:ref、reactive 与 Provide/Inject 完全指南
前端·javascript·vue.js
海天胜景2 小时前
vue3 el-table 行筛选 设置为单选
javascript·vue.js·elementui
今天又在摸鱼2 小时前
Vue3-组件化-Vue核心思想之一
前端·javascript·vue.js
百锦再2 小时前
Vue中对象赋值问题:对象引用被保留,仅部分属性被覆盖
前端·javascript·vue.js·vue·web·reactive·ref
jingling5552 小时前
面试版-前端开发核心知识
开发语言·前端·javascript·vue.js·面试·前端框架
木头没有瓜4 小时前
vscode离线安装插件
ide·vue.js·vscode
伍哥的传说4 小时前
鸿蒙系统(HarmonyOS)应用开发之手势锁屏密码锁(PatternLock)
前端·华为·前端框架·harmonyos·鸿蒙
浪裡遊5 小时前
Sass详解:功能特性、常用方法与最佳实践
开发语言·前端·javascript·css·vue.js·rust·sass
markyankee1016 小时前
使用 Vue 脚手架创建项目的完整指南
vue.js
青松学前端6 小时前
vue-2.7源码解读之初始化流程和响应式实现
前端·vue.js·前端框架