vue2 框架运行原理剖析系列(二)之 组件挂载$mount神秘之旅!!!

news2024/11/26 22:42:46

一、vue组件挂载

1.1 上一篇文章中,介绍到组件执行 mountComponent 函数,本文对此展开详细的讲解。
1.2 调用改方法的位置在于entry-runtime-with-compiler.js 的Vue.prototype.$mount,具体代码如下:
其中,
(1)el 是 实例化中,传入构造函数的el 选项,且options.render 的值不存在
(2)如果构造函数中,传入了template 选项,则template 的值就是把这个值处理成对应的template。
(3)如果template 不存在,其次会判断el 选项是否存在,如果存在,则根据文档文字,找到指定的标签包裹的HTML,作为template。
(4)以上方法在实例化 vue 中,存在el 选项的情况下执行,如果我们在开发过程中,没有使用这样方式创建,而是创建完之后,再挂载,也是可以的,这样就是用户手动触发该挂载函数,

Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  debugger
  el = el && query(el)
  //执行$mount 函数,会判断是否存在render 函数,不存在在则将template编译成渲染函数,把render赋值为改渲染函数
  const options = this.$options
  // resolve template/el and convert to render function
  if (!options.render) {
    let template = options.template
    if (template) {
      if (typeof template === 'string') {
        if (template.charAt(0) === '#') {
          template = idToTemplate(template)
          /* istanbul ignore if */
        }
      } else if (template.nodeType) {
        template = template.innerHTML
      } else {
        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }
    if (template) {
      /* istanbul ignore if */
      const { render, staticRenderFns } = compileToFunctions(template, {
        outputSourceRange: process.env.NODE_ENV !== 'production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns
    }
  }
  return mount.call(this, el, hydrating)
}

1.3 代码的解释可以对应到vue官网的生命周期示例图
在这里插入图片描述
1.4 是否存在el 的选项,实际上是在 init 函数的时候判断的,代码如下:

//文件位置 src/core/instance/init.js
if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }

1.5 挂载vue 的两种方式如下:
(1)用户手动触发 挂载函数,就是对于上图的对应的没有el 选项的情况

const app= new Vue();
app.$mount('.todoapp')

(2)实例化过程传入el选项

const app= new Vue({el:".todoapp"});

这两种方式实际上都会调用同一个方法,就是上面说的挂载函数,还会执行同样的判断逻辑。

二、模板 template 编译生成抽象语法树ast与渲染函数render生成

2.1 在我们实际过程中,我们把vue 的模板语法写到HTML 文件中,这样,如果没有经过特殊处理,浏览器都会把他们当做普通的文本处理,不会显示成我们想要的效果,那么,这一个步骤究竟是怎么实现的,下面我就带大家深入vue的模板编译。
2.2 在 一 中,介绍了template如何获取,那么下面就针对其接下来的要做的工作展开剖析,下一步代码如下:
将 获取到的template 传入 compileToFunctions 函数中 ,得到一个 render 和 staticRenderFns ,
然后将其赋值给 options,这个options 实际上就是指向 构造函数的参数对象

 const { render, staticRenderFns } = compileToFunctions(template, {
        outputSourceRange: process.env.NODE_ENV !== 'production',
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns

2.3 那么这个compileToFunctions 函数到底做了什么,其代码如下:

export const createCompiler = createCompilerCreator(function baseCompile (
  template: string,
  options: CompilerOptions
): CompiledResult {
  debugger
  const ast = parse(template.trim(), options)
  if (options.optimize !== false) {
    optimize(ast, options)
  }
  const code = generate(ast, options)
  return {
    ast,
    render: code.render,
    staticRenderFns: code.staticRenderFns
  }
})

2.4 其中,parse() 函数,是将template 编译成抽象语法树,其实际上就是一个对象,根据文档的嵌套结构,使用js 对象和其属性,模拟出来的一个表达其文档信息的对象,如下图所示:
在这里插入图片描述
2.5 得到抽象语法树之后,调用 generate(ast, options) 方法,把抽象语法树,作为参数,生成一个 code对象 ,code 具体样子如下:
在这里插入图片描述
2.6 其中code对象 render 值,就是一个函数,这个函数其实就是生成一个虚拟DOM 的函数,后面会在 _render 函数中调用这个函数

三、虚拟DOM 与 渲染函数与视图更新

3.1 mountComponent 的代码如下:
其中定义一个 updateComponent 方法用于更新视图,里面调用了vm._render(), 这个方法就是调用了二中的 render 函数,生成一个虚拟DOM ,然后执行vm._update 方法渲染真实的dom。
其中updateComponent 方法触发的机制是 数据方式变化是,由Watcher 调用 updateComponent 方法更新视图

xport function mountComponent (
  vm: Component,
  el: ?Element,
  hydrating?: boolean
): Component {
  // debugger
  vm.$el = el
  callHook(vm, 'beforeMount')
  let updateComponent
  /* istanbul ignore if */
   updateComponent = () => {
     vm._update(vm._render(), hydrating)
  }
  new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted && !vm._isDestroyed) {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
  hydrating = false
  // manually mounted instance, call mounted on self
  // mounted is called for render-created child components in its inserted hook
  if (vm.$vnode == null) {
    vm._isMounted = true
    callHook(vm, 'mounted')
  }
  return vm

3.2 vm._update 方法代码如下,其位置在src/core/instance/lifecycle 中,代码如下:
该方法 调用了patch 方法,进行新旧虚拟dom 的对比,然后更新视图,实现视图更新

 Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
    const vm: Component = this
    const prevEl = vm.$el
    const prevVnode = vm._vnode
    const restoreActiveInstance = setActiveInstance(vm)
    vm._vnode = vnode
    // Vue.prototype.__patch__ is injected in entry points
    // based on the rendering backend used.
    if (!prevVnode) {
      // initial render
      vm.$el = vm.__patch__(vm.$el, vnode, hydrating, false /* removeOnly */)
    } else {
      // updates
      vm.$el = vm.__patch__(prevVnode, vnode)
    }
    restoreActiveInstance()
    // update __vue__ reference
    if (prevEl) {
      prevEl.__vue__ = null
    }
    if (vm.$el) {
      vm.$el.__vue__ = vm
    }
    // if parent is an HOC, update its $el as well
    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
      vm.$parent.$el = vm.$el
    }
    // updated hook is called by the scheduler to ensure that children are
    // updated in a parent's updated hook.
  }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/513414.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【图像融合】Dif-Fusion:基于扩散模型的红外/可见图像融合方法

文章目录 摘要一、前言二、相关工作1.红外线和可见光的图像融合2.扩散模型(可见博主之前的博客) 三、方法1.红外线和可见光图像的联合扩散2*.多通道扩散特征的融合 四、实验1.实验设置2.融合性能分析(效果展示)3.泛化实验 总结 摘…

通知短信 API 技术细节以及发送流程机制原理解析

引言 短信是一种简单、直接、高效的通信方式,被广泛应用于各个领域。在移动互联网时代,短信成为了客户服务、政府通知、公共服务等方面的重要工具。为了更好地利用短信这种通信方式,通知短信 API应运而生。短信API可以帮助企业、政府和应用程…

RK3588旗舰32T人工智能多网口边缘智能网关交换机

32T边缘智能网关发布,助力多行业数字化升级,运维降本增效,搭载RK3588旗舰芯 搭载瑞芯微RK3588芯片的边缘智能网关XM-RK3588,算力可扩展至32T,适用于电力能源、智慧交通、智慧城市、智慧安防、智慧医疗、工业互联网等领…

前端的加密和解密,crypto-js的应用,AES / RSA / md5

每日鸡汤:每个你想学习的瞬间,都是未来你的向自己求救 内容预警*****新手内容,自己学习总结用****大佬请绕道 之前看https原理,看到对称加密和非对称加密,各种加密方法,看得云里雾里,即便是总结…

报错main.py: error: unrecognized arguments: stack_size 4 1001,770,123

运行从GitHub上面下载下来的代码时,按照作者提供的输入命令输入后报错: main.py: error: unrecognized arguments: stack_size 4 1001,770,123 将报错的部分在网上百度,找到部分方法,得出理解:输入的命令是出错的&am…

【RS专题】怎么知道你遇到的是rs风控

本文属于技术分享、如有侵权可联系本人下架 最简单的方法就是查看cookie,在控制台输入【document.cookie】 如果出现如上图中有【xxxxxxT】或者【xxxxxxP】的,并且它的值都为英文数字和下滑线加点,那么基本可以确定这个网站用了rs反爬 什么是rs反爬,下面抄一段内容 瑞数动…

【瑞数RS专题】首层代码分析,和获取eval层代码,cookie反爬虫详解

如有侵权、联系本人下架 以下面两个网站为例 1.aHR0cDovL3d3dy5mYW5nZGkuY29tLmNuL25ld19ob3VzZS9uZXdfaG91c2VfZGV0YWlsLmh0bWw= 2.aHR0cHM6Ly93d3cubm1wYS5nb3YuY24veWFvd2VuL3lwamd5dy9pbmRleC5odG1s 首先明确一下目标,我们要先获取网页200的源代码,RS5代第一次响应为…

unittest自动化测试框架讲解以及实战

为什么要学习unittest 按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,通常指函数或者类,一般是开发完成的。 单元…

软件架构:软件架构设计的三个维度

架构设计是一个非常大的话题,不管写几篇文章,接触到的始终只是冰山一角,更多的是实践中去体会。这篇文章主要介绍面向对象OO、面向方面AOP和面向服务SOA这三个要素在架构设计中的位置与作用。   架构设计有三个维度,或者说是我们…

文案改写神器软件-文案改编神器

文案改写神器软件 文案改写神器软件通常致力于通过人工智能技术将一篇已有文案进行改写和改编,以达到复用或优化的目的。以下是文案改写神器软件通常可以做的事情: 改写原文:文案改写神器可以通过自定义规则、语法分析和文本相似性匹配等功能…

设计模式之【组合模式】,树形结构的完美解决方案

文章目录 一、什么是组合模式1、组合模式三大角色2、组合模式应用场景3、组合模式注意事项和细节 二、透明组合模式1、学院院系案例2、透明组合模式总结 三、安全组合模式1、linux目录系统案例2、安全组合模式总结 四、源码中使用的组合模式1、HashMap2、ArrayList3、MyBatis 一…

跨平台应用开发进阶(六十一):uni-app 跨平台技术开发框架可行性调研

文章目录 一、流程类二、研发类(uni-app框架)三、心得分享(研发踩坑&uni-app踩坑)四、拓展阅读 一、流程类 IOS和安卓企业开发者账户申请流程(申请渠道、需要提供的相关证明、审核时间等)。 答:uni-app使用HBuliderX作为开发IDE,支持邮箱、密码方式注册&#x…

95、Image Restoration with Mean-Reverting Stochastic Differential Equations

简介 主页:https://github.com/Algolzw/image-restoration-sde 扩散模型终于在去噪、超分辨率等应用了。 这是一种基于随机微分方程的通用图像恢复方法,关键结构包括均值还原SDE,该SDE将高质量图像转换为具有固定高斯噪声的平均状态的降级…

怎么压缩png图片的大小?4个简单高效工具分享

怎么压缩png图片的大小?大家都知道jpg和png是目前电脑上最主流的两大图片文件格式,jpg图片的体积比较小,因为它属于有损压缩的图片格式,而png图片的体积相对就要大很多了,因为png属于无损压缩的图片格式。大家也同样知…

Redission实现分布式锁之源码解析

Redission实现分布式锁之源码解析 1、Redission实现分布式锁之源码解析1.1 分布式锁-redission功能介绍1.2 分布式锁-Redission快速入门1.3 分布式锁-redission可重入锁原理1.4 分布式锁-redission锁重试和WatchDog机制1.5 分布式锁-redission锁的MutiLock原理 1、Redission实现…

5G+工业互联网观察——应用篇

5G与工业互联网的结合是5G应用的重要领域,前一篇《5G工业互联网观察——政策篇》我们对5G工业互联网的相关政策进行了整理和分析,本篇继续从应用的角度整理目前的典型场景和重点行业,并进行简单的分析。 文 | 无界 全文4500字,预计…

原创 | 一文读懂蒙特卡洛算法

作者:陈之炎本文约2000字,建议阅读10分钟 本文介绍了蒙特卡洛算法。 蒙特卡洛算法(Monte Carlo algorithm)是一种基于随机采样的计算方法,其基本思想是通过生成随机样本,利用统计学原理来估计数学问题的解。…

MySQL实战之主从数据同步机制

主从同步的重要性: 解决数据可靠性的问题需要用到主从同步;解决 MySQL 服务高可用要用到主从同步;应对高并发的时候,还是要用到主从同步。 一、MySQL 主从同步流程 当客户端提交一个事务到 MySQL 的集群,直到客户端收…

《JavaEE初阶》Servlet

《JavaEE初阶》Servlet 文章目录 《JavaEE初阶》Servlet编写一个Servlet的helloworld1. 认识Maven并创建maven项目:2. 引入依赖:3.创建目录:4. 编写代码:5. 打包6. 部署7.验证 优化打包部署操作.常见的错误: ServletAPI:利用ajax构造请求.使用第三方工具postman构造请求HttpSer…

KDXL-A工频输电线路参数测试仪

一、简介 由我公司开发、研制的专门用于输电线路工频参数测量的高精度仪器,对于输电线路的一系列工频参数可进行精密的测量。 KDXL-A输电线路参数测试仪具有体积小、重量轻、测量准确度高、稳定性好、操作简便易学等优点,可取代以往利用多表法测量线路参数的方法&am…