热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Vue源码分析——生命周期

背景vue版本2.5.21本篇内容Vue的生命周期源码开始1.package.jsonscrpit内,npmrundev的命令:dev:rollup-w-cscriptsconfi

背景

vue版本

2.5.21

本篇内容

Vue的生命周期

源码开始

1. package.json

scrpit内,npm run dev的命令:

"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev"

  • 其中rollup是一个打包工具,类似webpack。

    rollup: Rollup 是一个 Javascript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。

  • 打包的代码在scripts/config.js

2. scripts/config.js

根据TARGET:web-full-dev找到如下代码:

// Runtime+compiler development build (Browser)
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: { he: './entity-decoder' },
banner
}

找到入口文件在web/entry-runtime-with-compiler.js

3. src\platforms\web\entry-runtime-with-compiler.js

vue来自于./runtime/index

import Vue from './runtime/index'

4. src\platforms\web\runtime\index.js

Vue来自于core/index

import Vue from 'core/index'
...
// public mount method
Vue.prototype.$mount = function (
el?: string | Element,
hydrating?: boolean
): Component {
el = el && inBrowser ? query(el) : undefined
return mountComponent(this, el, hydrating)
}

5. src\core\index.js

Vue来自于./instance/index

import Vue from './instance/index'

6. src\core\instance\index.js

一直跟到这里,Vue终于露出庐山真面目。

function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}

在定义了一个函数对象Vue后,接下来的代码:

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

我们一一分析。

6.1 initMixin src\core\instance\init.js

这里代码的作用是给Vue的原型链上定义_init方法。而这个_init方法在Vue对象创建时被调用(回看6里的代码this._init(options))。
接下来我们分析_init方法里做了什么,就明白了Vue对象创建时,到底经历了什么。
刚开始是一些参数的初始化,直到merge options。

export function initMixin (Vue: Class) {
Vue.prototype._init = function (options?: Object) {
...
// merge options
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)
} else {
vm.$optiOns= mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
} // expose real self
vm._self = vm
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') ...
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}

6.1.1 src\core\util\options.js

mergeOptions的方法做了什么?顾名思义,将options挂到Vue对象上。看下面的图:
《Vue源码分析——生命周期》
merge前vm.$options是空的;merge后,$options已经有值了。
执行完mergeOptions后,我们继续往下看。

6.1.2 initLifecycle src\core\instance\lifecycle.js

initLifecycle顾名思义,肯定与Vue的生命周期有关!真的是吗?同样看图:
《Vue源码分析——生命周期》
发现,只是多了一些参数,还没有到我们熟悉的created,mounted。但是这里是为生命周期做准备,做了一下初始化工作。

6.1.3 initEvents src\core\instance\events.js

这个方法的代码不多,主要是调用了updateComponentListeners方法。这个方法的作用是更新组件的侦听事件,与生命周期无关,暂不分析。

export function initEvents (vm: Component) {
vm._events = Object.create(null)
vm._hasHookEvent = false
// init parent attached events
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners)
}
}

6.1.4 initRender src\core\instance\render.js

initRender方法初始化了渲染的参数和方法(此时还没有渲染)。如下图:
《Vue源码分析——生命周期》

6.1.5 callHook(vm, 'beforeCreate')

终于到了第一个生命周期beforeCreate
接下来肯定是create了吧。

6.1.6 initInjections src\core\instance\inject.js

initInjections与provide/inject有关,与生命周期无关,这里暂不介绍。《Vue官方文档:provide/inject》

6.1.7 initState src\core\instance\state.js

代码不多,但是一看就知道是初始化Props,Methods,data,computed,watch的。

export function initState (vm: Component) {
vm._watchers = []
const opts = vm.$options
if (opts.props) initProps(vm, opts.props)
if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {
initData(vm)
} else {
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed)
if (opts.watch && opts.watch !== nativeWatch) {
initWatch(vm, opts.watch)
}
}

如图,将data(demo中没有methods等)的值注入:
《Vue源码分析——生命周期》

6.1.8 initProvide src\core\instance\inject.js

initProvide与provide/inject有关,与生命周期无关,这里暂不介绍。《Vue官方文档:provide/inject》
initProvide

6.1.9 callHook(vm, 'created')

第二个生命周期created

6.1.10 vm.$mount(vm.$options.el)

回看第4步中,给Vue的原型链上挂上了$mount方法:

import { mountComponent } from 'core/instance/lifecycle'
// public mount method
Vue.prototype.$mount = function (
...
}

6.1.10.1 mountComponent src\core\instance\lifecycle.js

export function mountComponent (
vm: Component,
el: ?Element,
hydrating?: boolean
): Component {
...
callHook(vm, 'beforeMount')
...
// updateComponent
new Watcher(vm, updateComponent, noop, {
before () {
if (vm._isMounted && !vm._isDestroyed) {
callHook(vm, 'beforeUpdate')
}
}
}, true /* isRenderWatcher */)
...
if (vm.$vnode == null) {
vm._isMounted = true
callHook(vm, 'mounted')
}
return vm
}

这段代码里,有关生命周期的就很多了。一共三个:beforeMount,beforeUpdate,mounted
真正mount的方法在updateComponent

updateCompOnent= () => {
vm._update(vm._render(), hydrating)
}

那么updateComponent何时调用?updateComponentnew Watcher时传进去,作为getter方法,在每次获取vm时执行,其中执行了vm._update(vm._render(), hydrating),用以mount渲染。
TODO: 这块代码具体会另起文章详细介绍。

原创说明

  • 本篇文章参考自

    • 《Github:liutao:从入口文件查看Vue源码.md》
    • 《Github:liutao:从一个小栗子查看Vue的生命周期.md》
  • 根据参考文章,本人结合Vue@2.5.21原创本篇内容(包括文字+图片)。
  • 转载请注明出处,谢谢。

推荐阅读
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • ### 优化后的摘要本学习指南旨在帮助读者全面掌握 Bootstrap 前端框架的核心知识点与实战技巧。内容涵盖基础入门、核心功能和高级应用。第一章通过一个简单的“Hello World”示例,介绍 Bootstrap 的基本用法和快速上手方法。第二章深入探讨 Bootstrap 与 JSP 集成的细节,揭示两者结合的优势和应用场景。第三章则进一步讲解 Bootstrap 的高级特性,如响应式设计和组件定制,为开发者提供全方位的技术支持。 ... [详细]
  • Spring Boot 实战(一):基础的CRUD操作详解
    在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
  • 深入浅出 webpack 系列(二):实现 PostCSS 代码的编译与优化
    在前一篇文章中,我们探讨了如何通过基础配置使 Webpack 完成 ES6 代码的编译。本文将深入讲解如何利用 Webpack 实现 PostCSS 代码的编译与优化,包括配置相关插件和加载器,以提升开发效率和代码质量。我们将详细介绍每个步骤,并提供实用示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • 如何使用ES6语法编写Webpack配置文件? ... [详细]
  • 本文介绍了如何利用ObjectMapper实现JSON与JavaBean之间的高效转换。ObjectMapper是Jackson库的核心组件,能够便捷地将Java对象序列化为JSON格式,并支持从JSON、XML以及文件等多种数据源反序列化为Java对象。此外,还探讨了在实际应用中如何优化转换性能,以提升系统整体效率。 ... [详细]
  • Java环境中Selenium Chrome驱动在大规模Web应用扩展时的性能限制分析 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • 分布式开源任务调度框架 TBSchedule 深度解析与应用实践
    本文深入解析了分布式开源任务调度框架 TBSchedule 的核心原理与应用场景,并通过实际案例详细介绍了其部署与使用方法。首先,从源码下载开始,详细阐述了 TBSchedule 的安装步骤和配置要点。接着,探讨了该框架在大规模分布式环境中的性能优化策略,以及如何通过灵活的任务调度机制提升系统效率。最后,结合具体实例,展示了 TBSchedule 在实际项目中的应用效果,为开发者提供了宝贵的实践经验。 ... [详细]
  • 在基于.NET框架的分层架构实践中,为了实现各层之间的松散耦合,本文详细探讨了依赖注入(DI)和控制反转(IoC)容器的设计与实现。通过合理的依赖管理和对象创建,确保了各层之间的单向调用关系,从而提高了系统的可维护性和扩展性。此外,文章还介绍了几种常见的IoC容器实现方式及其应用场景,为开发者提供了实用的参考。 ... [详细]
  • 利用 JavaScript 实现定时任务的高效执行方法(代码可直接复用) ... [详细]
  • 本课程详细解析了Spring AOP的核心概念及其增强机制,涵盖前置增强、后置增强和环绕增强等类型。通过具体示例,深入探讨了如何在实际开发中有效运用这些增强技术,以提升代码的模块化和可维护性。此外,还介绍了Spring AOP在异常处理和性能监控等场景中的应用,帮助开发者更好地理解和掌握这一强大工具。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • 本文探讨了如何通过检测浏览器类型来动态加载特定的npm包,从而优化前端性能。具体而言,仅在用户使用Edge浏览器时加载相关包,以提升页面加载速度和整体用户体验。此外,文章还介绍了实现这一目标的技术细节和最佳实践,包括使用User-Agent字符串进行浏览器识别、条件加载策略以及性能监控方法。 ... [详细]
author-avatar
菜蔸蔸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有