Vue2源码梳理:在 import Vue 时干了啥

分析导入入口

  • 在Web应用的 Vue.js 构建过程的 Runtime + Compiler 版本下,我们重点关注这个版本
  • 它的入口是 src/platforms/web/entry-runtime-with-compiler.js

1 ) entry-runtime-with-compiler.js 入口文件

  • 现在分析一下在 import Vue 的时候,都执行了哪些事情

  • entry-runtime-with-compiler.js

    /* @flow */import config from 'core/config'
    import { warn, cached } from 'core/util/index'
    import { mark, measure } from 'core/util/perf'import Vue from './runtime/index'
    import { query } from './util/index'
    import { compileToFunctions } from './compiler/index'
    import { shouldDecodeNewlines, shouldDecodeNewlinesForHref } from './util/compat'const idToTemplate = cached(id => {const el = query(id)return el && el.innerHTML
    })const mount = Vue.prototype.$mount
    Vue.prototype.$mount = function (el?: string | Element,hydrating?: boolean
    ): Component {el = el && query(el)/* istanbul ignore if */if (el === document.body || el === document.documentElement) {process.env.NODE_ENV !== 'production' && warn(`Do not mount Vue to <html> or <body> - mount to normal elements instead.`)return this}const options = this.$options// resolve template/el and convert to render functionif (!options.render) {let template = options.templateif (template) {if (typeof template === 'string') {if (template.charAt(0) === '#') {template = idToTemplate(template)/* istanbul ignore if */if (process.env.NODE_ENV !== 'production' && !template) {warn(`Template element not found or is empty: ${options.template}`,this)}}} else if (template.nodeType) {template = template.innerHTML} else {if (process.env.NODE_ENV !== 'production') {warn('invalid template option:' + template, this)}return this}} else if (el) {template = getOuterHTML(el)}if (template) {/* istanbul ignore if */if (process.env.NODE_ENV !== 'production' && config.performance && mark) {mark('compile')}const { render, staticRenderFns } = compileToFunctions(template, {shouldDecodeNewlines,shouldDecodeNewlinesForHref,delimiters: options.delimiters,comments: options.comments}, this)options.render = renderoptions.staticRenderFns = staticRenderFns/* istanbul ignore if */if (process.env.NODE_ENV !== 'production' && config.performance && mark) {mark('compile end')measure(`vue ${this._name} compile`, 'compile', 'compile end')}}}return mount.call(this, el, hydrating)
    }/*** Get outerHTML of elements, taking care* of SVG elements in IE as well.*/
    function getOuterHTML (el: Element): string {if (el.outerHTML) {return el.outerHTML} else {const container = document.createElement('div')container.appendChild(el.cloneNode(true))return container.innerHTML}
    }Vue.compile = compileToFunctionsexport default Vue
    
  • 这里可以看到 export default Vue 最终导出 Vue 对象

  • 而一开始的 Vue 的来源:import Vue from './runtime/index'

  • 之后,在其原型上挂载 $mount 方法

2 ) runtime/index 文件

  • 我们看下 runtime/index 文件中定义的Vue, 具体位置: src/platforms/web/runtime/index.js
    import Vue from 'core/index'
    import config from 'core/config'
    import { extend, noop } from 'shared/util'
    import { mountComponent } from 'core/instance/lifecycle'
    import { devtools, inBrowser, isChrome } from 'core/util/index'import {query,mustUseProp,isReservedTag,isReservedAttr,getTagNamespace,isUnknownElement
    } from 'web/util/index'import { patch } from './patch'
    import platformDirectives from './directives/index'
    import platformComponents from './components/index'// install platform specific utils
    Vue.config.mustUseProp = mustUseProp
    Vue.config.isReservedTag = isReservedTag
    Vue.config.isReservedAttr = isReservedAttr
    Vue.config.getTagNamespace = getTagNamespace
    Vue.config.isUnknownElement = isUnknownElement// install platform runtime directives & components
    extend(Vue.options.directives, platformDirectives)
    extend(Vue.options.components, platformComponents)// install platform patch function
    Vue.prototype.__patch__ = inBrowser ? patch : noop// public mount method
    Vue.prototype.$mount = function (el?: string | Element,hydrating?: boolean
    ): Component {el = el && inBrowser ? query(el) : undefinedreturn mountComponent(this, el, hydrating)
    }// ...export default Vue
    
    • 它最终也是 export default Vue, 而这里的 Vue 是从 core/index 而来
    • import 之后,它又定义了一些全局配置,挂载在 Vue.config 之上
    • 在 Vue 原型上又挂载了 __patch__ 方法 和 $mount 方法等

3 ) core/index 文件

  • 我们再进入 core/index,具体位置: src/core/index.js
    import Vue from './instance/index'
    import { initGlobalAPI } from './global-api/index'
    import { isServerRendering } from 'core/util/env'
    import { FunctionalRenderContext } from 'core/vdom/create-functional-component'initGlobalAPI(Vue)Object.defineProperty(Vue.prototype, '$isServer', {get: isServerRendering
    })Object.defineProperty(Vue.prototype, '$ssrContext', {get () {/* istanbul ignore next */return this.$vnode && this.$vnode.ssrContext}
    })// expose FunctionalRenderContext for ssr runtime helper installation
    Object.defineProperty(Vue, 'FunctionalRenderContext', {value: FunctionalRenderContext
    })Vue.version = '__VERSION__'export default Vue
    
    • 这里的 Vue 一开始 也是从其他地方导入而来的 import Vue from './instance/index'
    • 同时,initGlobalAPI(Vue) 这里初始化了一些 全局的 API
      • 这里定义了 Vue.config, 这里是全局config
      • 这里的 config 定义对应的在vue官网上相关的API文档可供参考
      • 还定义了 Vue.util 对象,里面有对应的方法,这里没有写在公共文档上
        • 这里不建议外部使用,因为里面的方法可能不稳定
      • 同时,这里是给 Vue 这个对象本身扩展全局的静态方法
        • 定义了 Vue.set, Vue.delete, Vue.nextTick, Vue.options 方法
        • Vue.options 用于合并方法,里面引用了 ASSET_TYPES
        • ASSET_TYPES 中又定义了 component, directive, filter 三个全局方法的枚举
      • Vue.options 上又挂载了 _base Vue.options._base = Vue
      • extend(Vue.options.components, builtInComponents) 这里的 builtInComponents 是内置组件
        • 里面只有 keep-alive 组件
      • 之后又调用了一系列的 init 方法
        • initUse(Vue) 创建了 vue.use 的全局方法
        • initMixin(Vue) 定义了一个全局的 mixin 方法
        • initExtend(Vue) 定义了 Vue.extend 方法
        • initAssetRegisters(Vue) 定义了上面ASSET_TYPES中枚举的全局 component, directive, filter 方法
      • 经过一些列初始化,我们才能在业务代码中使用这些代码
      • 可以进入 global-api/index 文件中查看,这里不再赘述, 参考 src/core/global-api/index.js
        export function initGlobalAPI (Vue: GlobalAPI) {// configconst configDef = {}configDef.get = () => configif (process.env.NODE_ENV !== 'production') {configDef.set = () => {warn('Do not replace the Vue.config object, set individual fields instead.')}}Object.defineProperty(Vue, 'config', configDef)// exposed util methods.// NOTE: these are not considered part of the public API - avoid relying on// them unless you are aware of the risk.Vue.util = {warn,extend,mergeOptions,defineReactive}Vue.set = setVue.delete = delVue.nextTick = nextTickVue.options = Object.create(null)ASSET_TYPES.forEach(type => {Vue.options[type + 's'] = Object.create(null)})// this is used to identify the "base" constructor to extend all plain-object// components with in Weex's multi-instance scenarios.Vue.options._base = Vueextend(Vue.options.components, builtInComponents)initUse(Vue)initMixin(Vue)initExtend(Vue)initAssetRegisters(Vue)
        }
        

4)instance/index 文件

  • 再进入 instance/index 文件
    import { initMixin } from './init'
    import { stateMixin } from './state'
    import { renderMixin } from './render'
    import { eventsMixin } from './events'
    import { lifecycleMixin } from './lifecycle'
    import { warn } from '../util/index'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)
    }initMixin(Vue)
    stateMixin(Vue)
    eventsMixin(Vue)
    lifecycleMixin(Vue)
    renderMixin(Vue)export default Vue
    
    • 在这里,就找到了 Vue 对象真正的定义的位置
    • 最上面,进行环境的判断,并且限制了 必须通过 new 来实例化
    • 之后执行 _init() 方法
    • 之后,调用了 一系列的 Minxin 的方法
      • initMixin 源码中,在 Vue 的原型上挂了 _init 方法
      • stateMixin 源码中,也是在 Vue中挂载了一些方法,比如: $set, $delete, $watch
      • … 其他都类似
      • 也就是说,每个 Minxin 就是在原型上汇入一些方法
    • 这里通过 function 的方式来声明 Vue, 比用 Class 好处在可以方便拆分方法的挂载
      • 拆分到不同文件下的好处是,方便代码的管理,有利于代码的维护
    • 这是非常值得学习的代码重构方案

5 )总结

  • 所以,到现在我们知道 Vue 本身就是一个基于函数实现的类,类上挂载了很多方法和属性
  • 对于 Vue 的初始化过程,总结出两个步骤
    • 一个是 Vue的定义,也就是最里层的那个 Vue function 的定义
    • 另一个是 属性和原型方法,全局方法,静态方法的挂载

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

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

相关文章

用户行为分析遇到的问题-ubantu16,hadoop3.1.3

用户行为分析传送门 我的版本 ubantu16 hadoop 3.1.3 habse 2.2.2 hive3.1.3 zookeeper3.8.3 sqoop 1.46/1.47 我sqoop把MySQL数据往hbase导数据时候有问题 重磅&#xff1a;大数据课程实验案例&#xff1a;网站用户行为分析&#xff08;免费共享&#xff09; 用户行为分析-小…

5G+云渲染技术:将如何快速推进XR和元宇宙?

XR&#xff08;扩展现实&#xff09;领域正在以惊人的速度增长。目前&#xff0c;到 2024 年&#xff0c;一些专家表示这个行业的价值将达到 3000 亿美元。 这个行业发展如此迅速的部分原因是 XR 将在商业环境中的带来巨大利益。近年来&#xff0c;很多企业遇到了将增强现实和…

RabbitMQ不公平分发问题分析及问题解决

1.不公平分发 1.1 不公平分发策略是什么&#xff1f; 在 RabbitMQ 中&#xff0c;不公平分发&#xff08;Unfair Dispatch&#xff09;是指当多个消费者&#xff08;Consumers&#xff09;同时订阅同一个队列&#xff08;Queue&#xff09;时&#xff0c;消息的分发机制是不公…

I.MX6ULL_Linux_驱动篇(48)linux I2C驱动

I2C 是很常用的一个串行通信接口&#xff0c;用于连接各种外设、传感器等器件。本章我们来学习一下如何在 Linux 下开发 I2C 接口器件驱动&#xff0c;重点是学习 Linux 下的 I2C 驱动框架&#xff0c;按照指定的框架去编写 I2C 设备驱动。本章同样以 I.MX6U-ALPHA 开发板上的 …

逻辑判断 | 判断推理

文章目录 翻译推理前推后(A->B)后推前(B->A)且和或 翻译推理 前推后(A->B) 关键词 如果 … 那么 …若 … 则 …只要 … 就 …为了 … 一定&#xff08;必须&#xff09;…所有 … , … 都… 是 … 的充分条件 后推前(B->A) 关键词 只有 … 才 …除非 …否则不…

Java数据结构-模拟ArrayList集合思想,手写底层源码(1),底层数据结构是数组,编写add添加方法,正序打印和倒叙打印

package com.atguigu.structure; public class Demo02_arrayList {public static void main(String[] args) {MyGenericArrayListV1 arrayListV1 new MyGenericArrayListV1();//arr.add(element:100,index:1);下标越界&#xff0c;无法插入//初始化&#xff08;第一次添加&…

Java 栈和队列的交互实现

文章目录 队列和栈的区别一.用队列模拟实现栈1.1入栈1.2出栈1.3返回栈顶元素1.4判断栈是否为空 二.用栈模拟实现队列2.1 入队2.2出队2.3peek2.4判断队列是否为空 三.完整代码3.1 队列模拟实现栈3.2栈模拟实现队列 队列和栈的区别 栈和队列都是常用的数据结构&#xff0c;它们的…

令人惊叹的代码技巧

在编程世界中&#xff0c;有一些令人惊叹的代码技巧和巧妙的实现方式。以下是一些我见过的令人印象深刻的代码技巧&#xff1a; 函数式编程魔法&#xff1a; 使用函数式编程的一些特性&#xff0c;比如高阶函数、匿名函数和Lambda表达式&#xff0c;可以使代码更为简洁、易读。…

飞天使-k8s知识点1-kubernetes架构简述

文章目录 名词功能要点 k8s核心要素CNCF 云原生框架简介k8s组建介绍 名词 CI 持续集成, 自动化构建和测试&#xff1a;通过使用自动化构建工具和自动化测试套件&#xff0c;持续集成可以帮助开发人员自动构建和测试他们的代码。这样可以快速检测到潜在的问题&#xff0c;并及早…

揭秘Spark学习框架网站:让你轻松掌握大数据处理神器!

介绍&#xff1a;Apache Spark是一个开源的大数据处理框架&#xff0c;它致力于实现高速、易用和复杂分析。Spark最初由加州大学伯克利分校的AMPLab于2009年开始开发&#xff0c;并于2010年成为Apache的开源项目之一。由于其出色的性能表现与丰富的功能特性&#xff0c;Spark已…

解决:Network ErrorAxiosError: Network Error at XMLHttpRequest.handleError

问题&#xff1a;Uncaught runtime errors&#xff1a;ERROR Network Error AxiosError: Network Error at XMLHttpRequest.handleError (webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:160:14) 解决&#xff1a;在Controller类上加上CrossOrigin注解 /**解…

【计算机四级(网络工程师)笔记】操作系统概论

目录 一、OS的概念 1.1OS的定义 1.2OS的特征 1.2.1并发性 1.2.2共享性 1.2.3随机性 1.3研究OS的观点 1.3.1软件的观点 1.3.2资源管理器的观点 1.3.3进程的观点 1.3.4虚拟机的观点 1.3.5服务提供者的观点 二、OS的分类 2.1批处理操作系统 2.2分时操作系统 2.3实时操作系统 2.4嵌…

SpringBoot之IOCDI的详细解析

3.3.2 IOC详解 通过IOC和DI的入门程序呢&#xff0c;我们已经基本了解了IOC和DI的基础操作。接下来呢&#xff0c;我们学习下IOC控制反转和DI依赖注入的细节。 3.3.2.1 bean的声明 前面我们提到IOC控制反转&#xff0c;就是将对象的控制权交给Spring的IOC容器&#xff0c;由…

c语言编写http服务器(Linux下运行)

参考文章&#xff1a;https://blog.csdn.net/baixingyubxy/article/details/125964986?spm1001.2014.3001.5506 上面是详细讲解&#xff0c;我这篇是总结了他的代码&#xff0c;因为他没给整体代码 所有代码&#xff1a; #include <stdio.h> #include <stdlib.h&g…

爬虫入门--爬取电影TOP250-附源码解析

爬取电影TOP250 1 知识小课堂1.1 什么是爬虫1.2 爬虫能做什么 2 代码解析2.1 运行环境2.2 过程解析2.2.1 第一步&#xff1a;引入两个模块2.2.2 找到网址2.2.3 拉去页面全内容 2.2.42.3 完整代码 1 知识小课堂 1.1 什么是爬虫 爬虫&#xff0c;也叫网络蜘蛛&#xff0c;如果把…

02 ModBus TCP

目录 一、ModBus TCP 一帧数据格式 二、0x01 读线圈状态 三、0x03读保持寄存器 四、0x05写单个线圈 五、0x06 写单个寄存器 六、0x0f写多个线圈 七、0x10&#xff1a;写多个保持寄存器 八、通信过程 九、不同modbus通信模式的应用场景 一、ModBus TCP 一帧数据格式 其…

图神经网络 (GNN) 概述

GNN 作者 with DALLE 3 一、说明 神经网络是受人脑工作启发的计算模型&#xff0c;能够从复杂的非结构化数据&#xff08;如图像、文本、音频和视频&#xff09;中学习。然而&#xff0c;还有许多其他类型的数据无法用传统的神经网络轻松表示&#xff0c;例如那些具有图形结构的…

Vue2面试题:说一下对跨域的理解?

http请求分为两大类&#xff1a;普通http请求&#xff08;如百度请求&#xff09;和ajax请求&#xff08;跨域是出现在ajax请求&#xff09; 同源策略&#xff1a;在浏览器发起ajax请求时&#xff0c;当前的网址和被请求的网址协议、域名、端口号必须完全一致&#xff0c;目的是…

windows平台配置vsCode_CMake_Clang/LLVM_ninja环境与测试

cmake配置 官网下载并安装 设置系统环境变量 cmake --versionvsCode插件 Clang/LLVM配置 vsCode clangd插件&#xff0c;提示安装lsp 官网下载LLVM 安装包安装&#xff0c;设置系统环境变量 clang --versionninja配置 官网下载 解压&#xff0c;设置系统环境变量 ninja -…

基于YOLOv8的结核病预测系统设计与实现

一、项目背景 本系统的目的是通过痰液图像来检测出结核杆菌的携带者&#xff0c;及时采取治疗措施&#xff0c;在病情早期对其进行相关治疗减少结核病的传播。程序使用的样本是经过染色处理可以使得结核杆菌在显微镜拍摄的医学图像&#xff0c;通过检测医学图像中的结核杆菌诊…