Vue生命周期源码解读(大厂面试必备)

什么是生命周期?

Vue的实例具有生命周期,Vue的实例在生成的时候,会经历一系列的初始化的过程;数据的监听,编译模板,实例挂载DOM元素,或者数据更新导致DOM更新,在执行的过程中,会运行一些叫做生命周期的钩子函数,在Vue实例生命周期中特定的时间点执行的函数称为生命周期的钩子函数;

如果我们需要在某个生命周期处理一些事情,我们可以把这些事情写在钩子函数中;等到Vue的实例生命周期到这个阶段就会执行这个钩子,而我们要做的事情也就得以处理了;

生命周期的钩子函数不能人为的控制其执行的顺序。

Vue生命周期梳理

总的来说,Vue的生命周期可以分为以下八个阶段:

  • beforeCreate 实例创建前
  • created 实例创建完成
  • beforeMount 挂载前
  • mounted 挂载完成
  • beforeUpdate 更新前
  • updated 更新完成
  • beforeDestory 销毁前
  • destoryed 销毁完成

大家可以参考一下官方资料 vue.js

1. vue实例化过程

从vue实例化开始分析,我们通过new Vue来实例化来查看一下源码 在 src/core/instance/init.js 中定义 使用vscode的小伙伴推荐使用Search node_modules插件查找node_modules中的插件方便多了,妈妈再也不用担心我迷路了

Vue.prototype._init = function (options?: Object) {
  // ... 省略代码
  initLifecycle(vm)
  initEvents(vm)
  initRender(vm)
  callHook(vm, 'beforeCreate')
  initInjections(vm) // resolve injections before data/props
  initState(vm)
  initProvide(vm) // resolve provide after data/props
  callHook(vm, 'created')

  /* istanbul ignore if */
  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
    vm._name = formatComponentName(vm, false)
    mark(endTag)
    measure(`vue ${vm._name} init`, startTag, endTag)
  }

  if (vm.$options.el) {
    vm.$mount(vm.$options.el)
  }
} 

Vue 初始化主要就干了几件事情,合并配置,初始化生命周期,初始化事件中心,初始化渲染,初始化 data、props、computed、watcher 等等,vue 把不同的功能逻辑拆成一些单独的函数执行。

我们关注到,在这个过程中插入钩子函数,提供给开发者调用的机会。在初始化的最后,检测到如果有 el 属性,则调用 vm.$mount 方法挂载 vm,挂载的目标就是把模板渲染成最终的 DOM。

2.生命周期钩子

  1. 生命周期钩子自动绑定this到实例上,因此你可以通过this.操作访问到数据和方法。注意不能使用箭头函数例如下方代码,因为箭头函数绑定外层的this会一直往上找。
created:()=>{// ...代码} 
  1. 下面用在各个生命周期中打印下el,data,dom节点
export default {
  name: 'App',
  data() {
    return {
      title: '标题'
    }
  },
   methods: {
    onDestoryClick() {
      this.$destroy()
    }
  },
  beforeCreate() {
    console.log(
      `\n\nbeforeCreate打头\n$el    :${this.$el}\n$data     :${JSON.stringify(
        this.$data
      )}\n$refs.head   :${JSON.stringify(
        this.$refs.head
      )}\nbeforeCreate结尾\n\n`
    )
    console.log(this.$vnode)
  },
  created() {
    console.log(
      `\n\ncreated打头\n$el    :${this.$el}\n$data     :${JSON.stringify(
        this.$data
      )}\n$refs.head   :${JSON.stringify(this.$refs.head)}\ncreated结尾\n\n`
    )
    console.log(this.$vnode)
  },
  beforeMount() {
    console.log(
      `\n\nbeforeMount打头\n$el    :${this.$el}\n$data     :${JSON.stringify(
        this.$data
      )}\n$refs.head   :${JSON.stringify(this.$refs.head)}\nbeforeMount结尾\n\n`
    )
    console.log(this.$vnode)
  },
  mounted() {
    console.log(
      `\n\nmounted打头\n$el    :${this.$el}\n$data     :${JSON.stringify(
        this.$data
      )}\n$refs.head   :${JSON.stringify(this.$refs.head)}\nmounted结尾\n\n`
    )
    console.log(this.$vnode)
  }
} 

可以发现

  1. beforeCreate中拿不到任何数据,它在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

  2. created中已经可以拿到data中的数据了,但是dom还没有挂载。会判断有无el,如果没有el则停止后面的模板挂载。

    在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。

    使用场景:ajax请求和页面初始化

  3. beforeMount 和 created 拿到的数据相同 在挂载开始之前被调用:相关的 render 函数首次被调用。

  4. mounted中el被创建dom已经更新,vue实例对象中有template参数选项,则将其作为模板编译成render函数,编译优先级render函数选项 > template选项

    使用场景:常用于获取VNode信息和操作,ajax请求

    注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted

  5. 由于beforeUpdate和updated使用的比较少,一般用计算属性和watch代替所以在此不在说明

  6. destroyed Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

客户端渲染过程

  1. 处理 HTML 标记并构建 DOM 树。
  2. 处理 CSS 标记并构建 CSSOM 树。
  3. 将 DOM 与 CSSOM 合并成一个渲染树。
  4. 根据渲染树来布局,以计算每个节点的几何信息。
  5. 将各个节点绘制到屏幕上。

最后,给大家分享一份2021最新Vue面试题含源码解析。由于篇幅原因,仅展示一部分面试题详解,更多最新的Vue面试题整理成了一个PDF,需要的朋友【点这里】免费领取。

vue-cli工程

  • 构建的 vue-cli 工程都到了哪些技术,它们的作用分别是什么?
  • vue-cli 工程常用的 npm 命令有哪些?
  • 请说出vue-cli工程中文件夹和文件的用处
  • config文件夹 下 index.js 的对于工程 开发环境 和 生产环境 的配置
  • 请你详细介绍一些 package.json 里面的配置

vue核心知识点

  • 对于Vue是一套渐进式框架的理解
  • vue.js的两个核心是什么?
  • 请问 v-if 和 v-show 有什么区别
  • vue常用的修饰符
  • v-on可以监听多个方法吗?
  • vue中 key 值的作用
  • vue-cli工程升级vue版本
  • vue事件中如何使用event对象?
  • $nextTick的使用
  • Vue 组件中 data 为什么必须是函数
  • v-for 与 v-if 的优先级
  • vue中子组件调用父组件的方法
  • vue中 keep-alive 组件的作用
  • vue中如何编写可复用的组件?
  • 什么是vue生命周期?
  • vue生命周期钩子函数有哪些?
  • vue如何监听键盘事件中的按键?
  • vue更新数组时触发视图更新的方法
  • vue中对象更改检测的注意事项
  • 解决非工程化项目初始化页面闪动问题
  • v-for产生的列表,实现active的切换
  • v-model语法糖的组件中的使用
  • vue中自定义过滤器
  • vue等单页面应用及其优缺点
  • 什么是vue的计算属性?
  • vue-cli提供的几种脚手架模板
  • vue父组件如何向子组件中传递数据?
  • vue弹窗后如何禁止滚动条滚动?
  • 计算属性的缓存和方法调用的区别
  • vue-cli中自定义指令的使用

vue-router

  • vue-router如何响应 路由参数 的变化?
  • 完整的 vue-router 导航解析流程
  • vue-router有哪几种导航钩子( 导航守卫 )?
  • vue-router传递参数的几种方式
  • vue-router的动态路由匹配
  • vue-router如何定义嵌套路由?
  • 组件及其属性
  • vue-router实现路由懒加载( 动态加载路由 )
  • vue-router路由的两种模式
  • history路由模式配置及后台配置

vuex

  • 什么是vuex?
  • 使用vuex的核心概念
  • vuex在vue-cli中的应用
  • 在vue中使用vuex,修改state的值
  • vuex actions异步修改状态

http请求

  • Promise对象是什么?
  • axios、fetch与ajax有什么区别?
  • 什么是JS的同源策略和跨域问题?
  • 如何解决跨域问题?
  • axios有什么特点?

UI样式

  • .vue组件的scoped属性的作用
  • 如何让CSS只在当前组件中起作用?
  • vue-cli中常用的UI组件库
  • 如何适配移动端?【 经典 】
  • 移动端媒体查询
  • vue内容垂直和水平居中
  • vue-cli引入图片的方法
  • 移动端常见样式问题
  • 文本超出隐藏

常用功能

  • vue中如何实现tab切换功能?
  • vue中keep-alive 实现标签页组件缓存
  • vue中实现页面从右往左侧滑入效果
  • vue中父子组件如何相互调用方法?
  • vue中央事件总线的使用

MVVM设计模式

  • MVC、MVP与MVVM模式
  • MVC、MVP与MVVM的区别
  • MVVM的实现原理
  • Object.defineProperty()方法
  • ES6中定义的类和对象
  • JS中的文档碎片
  • 解构赋值
  • Array.from
  • Array.reduce
  • 递归的使用
  • Obj.keys()与Obj.defineProperty
  • 发布-订阅模式
  • vue项目优化,缩短首屏加载时间

深入拓展

  • vue开发命令 npm run dev 输入后的执行过程
  • vue的服务器端渲染
  • 从零写一个npm安装包
  • vue-cli中常用到的加载器
  • webpack的特点

快速入手通道:【点击这免费领取2021最新Vue面试题含源码解析】

你的支持,我的动力;祝各位前程似锦,offer不断!!!

posted @ 2021-08-03 16:12  Android程序员吴彦祖  阅读(205)  评论(0编辑  收藏  举报