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

 更新时间:2024年11月22日 09:11:43   作者:疯狂的沙粒  
在 Vue.js 中,实例的挂载是一个非常重要的过程,它决定了 Vue 实例如何与 DOM 进行交互,通过分析 Vue 源码,特别是 Vue 的构建函数和生命周期,我们可以了解挂载过程的详细步骤,需要的朋友可以参考下

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

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

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

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

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

2.1 Vue 实例的构建函数

首先,我们来看 Vue 的构建函数,它通常是通过 new Vue(options) 来实例化 Vue 对象的。options 对象包含了组件的配置项,比如 eldatatemplate 等。

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);
}

在构造函数中,调用了 this._init(options),也就是实例化时 Vue 会调用内部的 _init 方法进行初始化。

2.2 Vue 的 _init 方法

Vue.prototype._init = function (options) {
  const vm = this;

  vm._uid = uid$1++; // 生成唯一 ID
  vm._isVue = true; // 标记 Vue 实例
  vm.$options = mergeOptions(
    resolveConstructorOptions(vm.constructor),
    options || {}
  ); // 合并构造函数默认选项和用户传入的选项
  vm._renderProxy = vm; // 渲染代理
  vm._self = vm; // 指向自己
  initLifecycle(vm); // 初始化生命周期
  initEvents(vm); // 初始化事件
  initRender(vm); // 初始化渲染
  callHook(vm, 'beforeCreate'); // 调用生命周期钩子 beforeCreate
  initState(vm); // 初始化数据、计算属性等
  initInjections(vm); // 处理依赖注入
  callHook(vm, 'created'); // 调用生命周期钩子 created
  if (vm.$options.el) {
    vm.$mount(vm.$options.el); // 挂载实例
  }
};
  • 生命周期的初始化:在 _init 方法中,Vue 会进行生命周期的初始化,并调用 beforeCreate 和 created 钩子。
  • 渲染代理_renderProxy 用于实现模板访问 this 时的代理。
  • $mount:如果传入了 el 选项,Vue 会调用 $mount 方法来挂载实例。

2.3 Vue 的 $mount 方法

挂载的核心方法是 $mount,它接受一个 DOM 元素或选择器字符串,并将 Vue 实例与这个 DOM 节点进行绑定。

Vue.prototype.$mount = function (el, hydrating) {
  el = el && query(el); // 如果传入了 el,进行选择并获取 DOM 元素
  if (el === document.body || el === document.documentElement) {
    warn('Do not mount Vue to <html> or <body> - mount to normal elements instead.');
    return;
  }
  const options = this.$options;
  if (!options.render) {
    let template = options.template;
    if (template) {
      if (typeof template === 'string') {
        // 编译模板
        template = compileToFunctions(template, this);
      }
    } else if (el) {
      // 没有模板时,从 DOM 中获取内容作为模板
      template = el.outerHTML;
    }
    options.render = template ? compileToFunctions(template, this) : createEmptyVNode;
  }
  return mountComponent(this, el, hydrating);
};
  • DOM 查询:首先,el 被解析成 DOM 元素。
  • 模板编译:如果没有传入渲染函数 (render),Vue 会尝试从模板字符串中编译生成渲染函数。
  • mountComponent:最后,调用 mountComponent 来进行组件的挂载。

2.4 mountComponent 方法

mountComponent 是挂载组件的核心方法,它会调用 vm.$el 将实例挂载到指定的 DOM 上。

function mountComponent(vm, el, hydrating) {
  vm.$el = el;
  callHook(vm, 'beforeMount');
  let updateComponent;
  
  // 这里通过 render 函数来渲染视图
  updateComponent = function () {
    vm._update(vm._render(), hydrating);
  };
  
  // 调用 Vue 的渲染函数,执行视图更新
  new Watcher(vm, updateComponent, noop, { before: callHook.bind(vm, 'beforeUpdate') }, true);
  callHook(vm, 'mounted');
  return vm;
}
  • 调用 beforeMount:在渲染之前,会先执行 beforeMount 生命周期钩子。
  • 渲染和更新updateComponent 会触发 vm._update 方法进行视图更新。_render() 是用于生成虚拟 DOM 的方法,它会调用渲染函数。
  • Watcher:Vue 通过 Watcher 来观察响应式数据的变化,并在数据变化时触发更新。

2.5 Vue 的 _update 方法

_update 方法会根据虚拟 DOM 的变化,重新渲染并更新 DOM。

Vue.prototype._update = function (vnode, hydrating) {
  const vm = this;
  const prevEl = vm.$el;
  const prevVnode = vm._vnode;
  vm._vnode = vnode;
  if (!prevVnode) {
    // 初次渲染
    vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */);
  } else {
    // 更新渲染
    vm.$el = vm.__patch__(prevVnode, vnode);
  }
  // 更新生命周期钩子
  callHook(vm, 'updated');
};
  • 虚拟 DOM 比对_update 会执行虚拟 DOM 与真实 DOM 的比对,更新页面内容。
  • 生命周期钩子:更新后,会调用 updated 生命周期钩子。

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

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

  1. 初始化实例:通过 new Vue(options) 创建 Vue 实例,调用 _init 方法进行初始化。
  2. 编译模板:如果没有传入 render 函数,Vue 会通过模板字符串生成渲染函数。
  3. 挂载组件:通过 $mount 方法将 Vue 实例挂载到指定的 DOM 元素上。
  4. 渲染更新:通过 _update 方法更新 DOM,生成新的视图。
  5. 生命周期钩子:在每个阶段会触发相应的生命周期钩子函数(如 beforeCreatecreatedbeforeMountmounted 等)。

通过以上分析,我们可以理解 Vue 实例挂载的完整过程,以及其中涉及的关键函数和生命周期钩子。

到此这篇关于Vue实例创建和挂载的详细过程的文章就介绍到这了,更多相关Vue实例创建和挂载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一步步教你利用webpack如何搭一个vue脚手架(超详细讲解和注释)

    一步步教你利用webpack如何搭一个vue脚手架(超详细讲解和注释)

    这篇文章主要给大家介绍了软玉利用webpack如何搭一个vue脚手架的相关资料,文中有超详细讲解和注释,对大家学习或者使用webpack具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-01-01
  • Vue+Echarts实现基本K线图的绘制

    Vue+Echarts实现基本K线图的绘制

    这篇文章主要为大家详细介绍了如何利用Vue和Echarts实现基本K线图的绘制,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-03-03
  • 浅谈Vue.js 1.x 和 2.x 实例的生命周期

    浅谈Vue.js 1.x 和 2.x 实例的生命周期

    下面小编就为大家带来一篇浅谈Vue.js 1.x 和 2.x 实例的生命周期。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • 关于IDEA中的.VUE文件报错 Export declarations are not supported by current JavaScript version

    关于IDEA中的.VUE文件报错 Export declarations are not supported by cu

    这篇文章主要介绍了关于IDEA中的.VUE文件报错 Export declarations are not supported by current JavaScript version的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • Vue封装的组件全局注册并引用

    Vue封装的组件全局注册并引用

    这篇文章主要为大家详细介绍了Vue封装的组件全局注册并引用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-07-07
  • vue3在单个组件中实现类似mixin的事件调用

    vue3在单个组件中实现类似mixin的事件调用

    这篇文章主要为大家详细介绍了vue3如何在单个组件中实现类似mixin的事件调用,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • Vue3响应式对象数组不能实时DOM更新问题解决办法

    Vue3响应式对象数组不能实时DOM更新问题解决办法

    在写大文件上传时,碰到关于 vue2 跟 vue3 对在循环中使用异步,并动态把普通对象添加进响应式数据,在异步前后修改该普通对象的某个属性,导致 vue2 跟 vue3 的视图更新不一致,引发一系列的思考,所以本文介绍了Vue3响应式对象数组不能实时DOM更新问题解决办法
    2024-07-07
  • Vuex的四个常用核心概念解读

    Vuex的四个常用核心概念解读

    本文详细解析了Vuex中的四个核心概念及其区别,包括State用于存储状态,Getters用于计算属性并缓存,Mutations是唯一更改State的同步方法,Actions则用于提交Mutations且支持异步操作
    2024-11-11
  • Vue2.0 组件传值通讯的示例代码

    Vue2.0 组件传值通讯的示例代码

    本篇文章主要介绍了Vue2.0 组件传值通讯的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • 一文教你如何优雅的控制全局loading的显示

    一文教你如何优雅的控制全局loading的显示

    在我们的平时的工作中,在前后端交互的时候,为了提高页面的观赏性和用户的体验,我们会在页面上添加loading来阻止用户操作来等待接口的返回,这篇文章主要给大家介绍了关于如何优雅的控制全局loading显示的相关资料,需要的朋友可以参考下
    2022-01-01

最新评论