翼度科技»论坛 编程开发 JavaScript 查看内容

Vue实例创建和挂载的详细过程

8

主题

8

帖子

24

积分

新手上路

Rank: 1

积分
24
1. Vue 实例创建和挂载的过程概述

Vue 实例的挂载过程涉及多个关键步骤,包括创建实例、编译模板、初始化数据和事件绑定等。它的核心流程大致如下:

  • 初始化 Vue 实例:在
    1. new Vue()
    复制代码
    调用时,Vue 实例会创建并初始化相关的属性,如
    1. data
    复制代码
    1. computed
    复制代码
    1. methods
    复制代码
    等。
  • 初始化生命周期:Vue 会初始化生命周期钩子,包括
    1. beforeCreate
    复制代码
    1. created
    复制代码
    1. beforeMount
    复制代码
    1. mounted
    复制代码
    等。
  • 编译模板:Vue 会解析传入的模板,生成虚拟 DOM(VNode)。
  • 渲染:将虚拟 DOM 转换为真实的 DOM,最终将 Vue 实例挂载到指定的 DOM 节点上。
  • 更新:在响应式数据变化时,Vue 会触发更新,重新渲染组件。

2. 分析源码:Vue 实例的创建与挂载过程

我们从 Vue 2.x 的源码分析 Vue 实例的挂载过程。以下是大致的分析步骤。

2.1 Vue 实例的构建函数

首先,我们来看 Vue 的构建函数,它通常是通过
  1. new Vue(options)
复制代码
来实例化 Vue 对象的。
  1. options
复制代码
对象包含了组件的配置项,比如
  1. el
复制代码
  1. data
复制代码
  1. template
复制代码
等。
  1. function Vue(options) {
  2.   if (process.env.NODE_ENV !== 'production' && !(this instanceof Vue)) {
  3.     warn('Vue is a constructor and should be called with the `new` keyword');
  4.   }
  5.   this._init(options);
  6. }
复制代码
在构造函数中,调用了
  1. this._init(options)
复制代码
,也就是实例化时 Vue 会调用内部的
  1. _init
复制代码
方法进行初始化。

2.2 Vue 的 _init 方法
  1. Vue.prototype._init = function (options) {
  2.   const vm = this;

  3.   vm._uid = uid$1++; // 生成唯一 ID
  4.   vm._isVue = true; // 标记 Vue 实例
  5.   vm.$options = mergeOptions(
  6.     resolveConstructorOptions(vm.constructor),
  7.     options || {}
  8.   ); // 合并构造函数默认选项和用户传入的选项
  9.   vm._renderProxy = vm; // 渲染代理
  10.   vm._self = vm; // 指向自己
  11.   initLifecycle(vm); // 初始化生命周期
  12.   initEvents(vm); // 初始化事件
  13.   initRender(vm); // 初始化渲染
  14.   callHook(vm, 'beforeCreate'); // 调用生命周期钩子 beforeCreate
  15.   initState(vm); // 初始化数据、计算属性等
  16.   initInjections(vm); // 处理依赖注入
  17.   callHook(vm, 'created'); // 调用生命周期钩子 created
  18.   if (vm.$options.el) {
  19.     vm.$mount(vm.$options.el); // 挂载实例
  20.   }
  21. };
复制代码

  • 生命周期的初始化:在
    1. _init
    复制代码
    方法中,Vue 会进行生命周期的初始化,并调用
    1. beforeCreate
    复制代码
    1. created
    复制代码
    钩子。
  • 渲染代理
    1. _renderProxy
    复制代码
    用于实现模板访问
    1. this
    复制代码
    时的代理。
    1. $mount
    复制代码
    :如果传入了
    1. el
    复制代码
    选项,Vue 会调用
    1. $mount
    复制代码
    方法来挂载实例。

2.3 Vue 的 $mount 方法

挂载的核心方法是
  1. $mount
复制代码
,它接受一个 DOM 元素或选择器字符串,并将 Vue 实例与这个 DOM 节点进行绑定。
  1. Vue.prototype.$mount = function (el, hydrating) {
  2.   el = el && query(el); // 如果传入了 el,进行选择并获取 DOM 元素
  3.   if (el === document.body || el === document.documentElement) {
  4.     warn('Do not mount Vue to <html> or <body> - mount to normal elements instead.');
  5.     return;
  6.   }
  7.   const options = this.$options;
  8.   if (!options.render) {
  9.     let template = options.template;
  10.     if (template) {
  11.       if (typeof template === 'string') {
  12.         // 编译模板
  13.         template = compileToFunctions(template, this);
  14.       }
  15.     } else if (el) {
  16.       // 没有模板时,从 DOM 中获取内容作为模板
  17.       template = el.outerHTML;
  18.     }
  19.     options.render = template ? compileToFunctions(template, this) : createEmptyVNode;
  20.   }
  21.   return mountComponent(this, el, hydrating);
  22. };
复制代码

  • DOM 查询:首先,
    1. el
    复制代码
    被解析成 DOM 元素。
  • 模板编译:如果没有传入渲染函数 (
    1. render
    复制代码
    ),Vue 会尝试从模板字符串中编译生成渲染函数。
    1. mountComponent
    复制代码
    :最后,调用
    1. mountComponent
    复制代码
    来进行组件的挂载。

2.4 mountComponent 方法
  1. mountComponent
复制代码
是挂载组件的核心方法,它会调用
  1. vm.$el
复制代码
将实例挂载到指定的 DOM 上。
  1. function mountComponent(vm, el, hydrating) {
  2.   vm.$el = el;
  3.   callHook(vm, 'beforeMount');
  4.   let updateComponent;
  5.   
  6.   // 这里通过 render 函数来渲染视图
  7.   updateComponent = function () {
  8.     vm._update(vm._render(), hydrating);
  9.   };
  10.   
  11.   // 调用 Vue 的渲染函数,执行视图更新
  12.   new Watcher(vm, updateComponent, noop, { before: callHook.bind(vm, 'beforeUpdate') }, true);
  13.   callHook(vm, 'mounted');
  14.   return vm;
  15. }
复制代码

  • 调用
    1. beforeMount
    复制代码
    :在渲染之前,会先执行
    1. beforeMount
    复制代码
    生命周期钩子。
  • 渲染和更新
    1. updateComponent
    复制代码
    会触发
    1. vm._update
    复制代码
    方法进行视图更新。
    1. _render()
    复制代码
    是用于生成虚拟 DOM 的方法,它会调用渲染函数。
  • Watcher:Vue 通过
    1. Watcher
    复制代码
    来观察响应式数据的变化,并在数据变化时触发更新。

2.5 Vue 的 _update 方法
  1. _update
复制代码
方法会根据虚拟 DOM 的变化,重新渲染并更新 DOM。
  1. Vue.prototype._update = function (vnode, hydrating) {
  2.   const vm = this;
  3.   const prevEl = vm.$el;
  4.   const prevVnode = vm._vnode;
  5.   vm._vnode = vnode;
  6.   if (!prevVnode) {
  7.     // 初次渲染
  8.     vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
  9.   } else {
  10.     // 更新渲染
  11.     vm.$el = vm.__patch__(prevVnode, vnode);
  12.   }
  13.   // 更新生命周期钩子
  14.   callHook(vm, 'updated');
  15. };
复制代码

  • 虚拟 DOM 比对
    1. _update
    复制代码
    会执行虚拟 DOM 与真实 DOM 的比对,更新页面内容。
  • 生命周期钩子:更新后,会调用
    1. updated
    复制代码
    生命周期钩子。

3. 总结 Vue 实例挂载的过程

Vue 实例的挂载过程包含以下几个主要步骤:

  • 初始化实例:通过
    1. new Vue(options)
    复制代码
    创建 Vue 实例,调用
    1. _init
    复制代码
    方法进行初始化。
  • 编译模板:如果没有传入
    1. render
    复制代码
    函数,Vue 会通过模板字符串生成渲染函数。
  • 挂载组件:通过
    1. $mount
    复制代码
    方法将 Vue 实例挂载到指定的 DOM 元素上。
  • 渲染更新:通过
    1. _update
    复制代码
    方法更新 DOM,生成新的视图。
  • 生命周期钩子:在每个阶段会触发相应的生命周期钩子函数(如
    1. beforeCreate
    复制代码
    1. created
    复制代码
    1. beforeMount
    复制代码
    1. mounted
    复制代码
    等)。
通过以上分析,我们可以理解 Vue 实例挂载的完整过程,以及其中涉及的关键函数和生命周期钩子。
到此这篇关于Vue实例创建和挂载的详细过程的文章就介绍到这了,更多相关Vue实例创建和挂载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

来源:https://www.jb51.net/javascript/331170tdk.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具