• vue源码分析-从new Vue开始


    初学vue,你得知道我们是从new Vue开始的:

    new Vue({
       
      el: '#app',
      data: obj,
      ...
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    那你觉得是不是很有意思,咱们new Vue之后,就可以使用他那么多的功能,可见Vue是暴出来的一个一个功能类函数,我们进入源码一探究竟:

    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'
    /** * 添加全局的API */
    initGlobalAPI(Vue)
    /** * 服务端渲染需要 */
    Object.defineProperty(Vue.prototype, '$isServer', {
       
      get: isServerRendering
    })
    /** * 服务端渲染需要 */
    Object.defineProperty(Vue.prototype, '$ssrContext', {
       
      get () {
       
        /* istanbul ignore next */
        return this.$vnode && this.$vnode.ssrContext
      }
    })
    /** * 服务端渲染需要 */
    Object.defineProperty(Vue, 'FunctionalRenderContext', {
       
      value: FunctionalRenderContext
    })
    /** * vue版本号 这里的'__VERSION__'为占位符,发布版本时将被自动替换 */
    Vue.version = '__VERSION__'
    export default Vue
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    那么我们看到咱们的核心Vue来自'./instance/index'那我们再去一探究竟,可想而知里面必定有一个Vue函数类

    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'
    
    // Vue构造函数必须使用new关键字实例化, 否则会抛出一个警告, 实例化Vue的时候会调用_init方法初始化
    // 这里options也是.vue文件中暴露出的对象
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    可以看到里面有一个function Vue功能类,而且里面加载了initMixin,stateMixin等,这几个方法分别传入了Vue来初始化一些功能。
    另外我们可以在入口文件出看到initGlobalAPI这个方法,那么我们打开initGlobalAPI所在的位置:./global-api/index

    参考Vue3源码视频讲解:进入学习

    ......
    export function initGlobalAPI (Vue: GlobalAPI) {
       
      // config
      // 提供获取配置项的方法, 不允许在这里设置配置项
      const configDef = {
       }
      configDef.get = () => config
      if (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.
      // 注册全局工具API, 只对Vue生效。
      Vue.util = {
       
        warn,
        extend,
        mergeOptions,
        defineReactive
      }
      //定义全局属性
      Vue.set = set
      Vue.delete = del
      Vue.nextTick = nextTick
    
      // 初始化options
      Vue.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.
      // 用_base属性来挂载Vue构造器
      Vue.options._base = Vue
    
      extend(Vue.options.components, builtInComponents)
      //定义全局方法
      initUse(Vue) // Vue.use
      initMixin(Vue) // Vue.mixin
      initExtend(Vue) // Vue.extend
      initAssetRegisters(Vue)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    可见暴露出多个方法给全局,而Vue.util是一些工具方法:

    import config from '../config'
    import {
        initUse } from './use'
    import {
        initMixin } from './mixin'
    import {
        initExtend } from './extend'
    import {
        initAssetRegisters } from './assets'
    import {
        set, del } from '../observer/index'
    import {
        ASSET_TYPES } from 'shared/constants'
    import builtInComponents from '../components/index'
    
    import {
       
      warn,
      extend,
      nextTick,
      mergeOptions,
      defineReactive
    } from '../util/index'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    那么我们回到Vue功能函数类上:

    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'
    
    // Vue构造函数必须使用new关键字实例化, 否则会抛出一个警告, 实例化Vue的时候会调用_init方法初始化
    // 这里options也是.vue文件中暴露出的对象
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    我们可以看到initMixin(Vue)执行了,那么我们去读一下init的源码:

    import config from '../config'
    import {
        initProxy } from './proxy'
    import {
        initState } from './state'
    import {
        initRender } from './render'
    import {
        initEvents } from './events'
    import {
        mark, measure } from '../util/perf'
    import {
        initLifecycle, callHook } 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    大规模 Transformer 模型 8 比特矩阵乘简介 - 基于 Hugging Face Transformers、Accelerate 以及 bitsandbytes
    香港写字楼等级如何划分?从3A到C级一文讲明白
    Android多版本flavor配置之资源文件和清单文件合并介绍
    [英雄星球七月集训LeetCode解题日报] 第1日 数组
    并发编程的工具类
    Java解析MDB(上)-纯JDBC解析非空间数据
    编译原理复习——文法和语言2
    学习笔记——交通安全分析13
    KT6368A双模蓝牙芯片串口与mcu之间串接的电阻以及电平转换说明
    Java中的自动装箱与自动拆箱
  • 原文地址:https://blog.csdn.net/yyzzabc123/article/details/127782746