vue初始化——源码简读

源码目录结构

  • 这里主要分析src目录下文件的主要功能
    • compiler:与编译相关
    • coreVue核心代码
      • componentskeep-alive相关代码
      • global-apiVue静态成员相关初始化
      • instanceVue实例相关初始化
      • observer:响应式相关代码
      • vdom:虚拟dom相关代码
    • platform:平台相关代码
    • serverVueSSR服务端渲染相关代码

Vue的构建版本

  • 在执行npm run build时,会生成vue的不同版本,下面我们具体看一下各版本区别
版本UMDCommonJSES Module
完整版vue.jsvue.common.jsvue.esm.js
只包含运行时版vue.runtime.jsvue.runtime.common.jsvue.runtime.esm.js
完整版 (生产环境)Vue.min.js
只包含运行时版 (生产环境)Vue.runtime.min.js
  • 完整版:同时包含编译器和运行时的版本。
  • 编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码,体积大,效率低。
  • 运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。体积小,效率高,基本上就是除去编译器的其它一切。
  • UMD: 通用的模块版本,支持多种模块方式。UMD 版本可以通过 <script> 标签直接用在浏览器中
  • CommonJS(cjs): CommonJS配合老的打包工具,比如BrowserifyWebpack1
  • ES Modules:从2.6开始Vue会提供两个ES Modules(ESM)构建文件,为现代打包工具提供的版本。
  • ESM格式被设计为可以被静态分析,所以打包工具利用这一点可以进行TreeShaking,并将用不到的代码排除最终的包

完整版与运行时版本的区别

  • 完整版:即需要将template转为render函数,创建Vue实例,渲染并处理DOM等代码
<script src="../../dist/vue.min.js"></script>
 <div id="app"></div>

  <script>
    const vm = new Vue({
      el: '#app',
      template: '<h1>{{msg}}</h1>',
      data: {
        msg: 'Hello World'
      }
    })
  </script>
  • 运行时版本:不需要将template转为render函数,创建Vue实例,渲染并处理DOM等代码,此时将vue.min.js换为运行时版本
<script src="../../dist/vue.runtime.js"></script>

在这里插入图片描述

  • 此时会出现报错,下面我们将template换为render函数,则可以正常运行,如下:
<script>
    const vm = new Vue({
      el: '#app',
      render(h){
        return h('h1', this.msg)
      },
      data: {
        msg: 'Hello World'
      }
    })
</script>
  • 基于vue-cli搭建的项目,默认引入的vue是运行时版本,且是ESM模块化方式
  • vue脚手架创建的Vue项目中,引用的Vue版本就是运行时版本:vue.runtime.esm.js,我们可以在Vue项目中执行:vue inspect > output.js,将webpack配置输出到output.js文件中查看:
resolve: {
    alias: {
      '@': 'D:\\work\\vue源码\\code\\01-demo\\src',
      vue$: 'vue/dist/vue.runtime.esm.js'
    },
}

template与render执行顺序

  • 打开文件src/platform/web/entry-runtime-with-compiler.js, 找到Vue.prototype.$mount函数
  • 在该函数中,会优先判断是否有render选项,如果有,则调用mount,进行DOM挂载,如果没有,才会通过template来生成render函数
  • 因此rendertemplate的优先级为:render > template, 源码如下:在这里插入图片描述

Vue函数的初始化

  1. 首先先找到打包文件入口,也就是src/platform/web/entry-runtime-with-compiler.js**,该文件主要实现两个功能:
    1)重写了$mount方法,使其可以对template的字符串,可以转为render函数
    2)注册了Vue.compile()方法,这个方式就是templaterender函数的方法

在这里插入图片描述


  1. 但上面的文件并没有进行Vue构造函数的定义,因此根据上面引入的Vue打开src/platform/web/runtime/index继续分析代码,该文件主要实现三个功能:
    1)注册全局指令与组件,全局的指令与组件都在Vue.options.directivesVue.options.components
    2)注册__patch__函数,主要用于将虚拟DOM转为真实DOM
    3)注册$mount方法,用于组件挂载
    在这里插入图片描述

  1. 上面文件中的Vue引自于core/index, 在该文件中,主要实现两部分功能:
    1)在initGlobalAPI中为Vue的构造函数增加一些静态成员
    2)给Vue增加一些与VueSSR相关的成员

在这里插入图片描述


  1. 最后,我们根据core/index中引入的Vue打开文件src/core/instance/index.js, 在这个文件中,定义了Vue函数,其中:
    1)在Vue构造函数中调用了_init方法,
    2)给Vue中混入了常用的实例成员

在这里插入图片描述

Vue静态方法初始化

  1. 我们在上面说过在initGlobalAPI函数中为Vue的构造函数增加一些静态成员,下面我们来具体看一下initGlobalAPI函数,在src/core/global-api/index.js文件中
  2. 下面两张截图中分别标注除了对应代码的作用,因为在initGlobalAPI主要做了以下几件事
    1)初始化Vue.config属性
    2)注册setdeletenextTick
    3)注册Vue.observable,该函数主要用于将一个对象编程可响应式
    4)初始化Vue.options.components,Vue.options.directives, Vue.options.filters
    5)存储Vue构造函数在Vue.options._base
    6)通过extend注册keep-alive组件
    7)注册Vue.use() 用来注册插件
    8)注册Vue.mixin() 实现混入
    9)注册Vue.extend() 基于传入的options返回一个组件的构造函数
    10)注册Vue.directive() Vue.component() Vue.filter()

在这里插入图片描述
在这里插入图片描述

Vue实例成员初始化过程

上面介绍了Vue静态方法的初始化,现在我们来看一下Vue实例的初始化,Vue实例的初始化是在文件src/core/instance/index.js

  • 1)注册了vm_init()方法
  • 2)初始化了事件相关的方法,$on/$once/$off/$emit,其中事件的原理是发布订阅
  • 3)初始化生命周期相关的方法,_update/$forceupdate/$destory
  • 4)初始化render$nextTick/_render

在这里插入图片描述

Vue实例成员init方法

在上面了解到,在初始化一个Vue实例的时候,会调用_init方法,下面我们来简单看一下_init方法内部的实现
该函数主要用于options合并,vue实例初始化,与触发beforeCreatedcreated生命周期的钩子函数

在这里插入图片描述

在这里插入图片描述

Vue实例成员initState方法

  1. 下面具体来看一下initState内部方法的实现
  2. 该方法相对比较简单,主要进行了以下操作
    1)initProps:将props中成员转为为响应式,并注入到vue实例中
    2)将methods中的方法注入到vue实例,在注入之前会检查是否有与prop重名的方法名,及检查methods的命名规范
    3)初始化data,如果传入data则调用initData方法,否则初始化vm._data,并将其赋值为空对象
    4)初始化计算属性computed与监听器watcher,并将其注入到vue实例
  3. initData方法中
    1)初始化_data, 如果组件中data是函数,则调用函数的返回结果,否则直接返回data
    2)判断在propsmethods中是否有重名属性,及检查命名规范
    3)将_data注入到vue实例中,并将其设置为响应式数据

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值