面试时这样回答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^

相关推荐
陈小白_weilin6 分钟前
VUE-CLI配置全局SCSS变量
vue.js·scss
For. tomorrow14 分钟前
Vue3中el-table组件实现分页,多选以及回显
前端·vue.js·elementui
布瑞泽的童话41 分钟前
无需切换平台?TuneFree如何搜罗所有你爱的音乐
前端·vue.js·后端·开源
小贵子的博客1 小时前
ElementUI 用span-method实现循环el-table组件的合并行功能
javascript·vue.js·elementui
码上飞扬1 小时前
前端框架对比选择:如何在众多技术中找到最适合你的
vue.js·前端框架·react·angular·svelte
哈哈哈hhhhhh2 小时前
vue 入门一
前端·javascript·vue.js
尸僵打怪兽2 小时前
后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0916)
vue.js·vue
Passion不晚5 小时前
Vue vs React vs Angular 的对比和选择
vue.js·react.js·前端框架·angular.js
Jiaberrr11 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
LvManBa11 小时前
Vue学习记录之六(组件实战及BEM框架了解)
vue.js·学习·rust