美文网首页
vue源码第一天

vue源码第一天

作者: e80c3fbed5b2 | 来源:发表于2020-06-18 22:59 被阅读0次

vue源码目录结构

简单,干净,明了,清晰

src
├── compiler        # 编译相关 
├── core            # 核心代码 
├── platforms       # 不同平台的支持
├── server          # 服务端渲染
├── sfc             # .vue 文件解析
├── shared          # 共享代码

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'

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是一个function类,为什么不用es6的class呢?因为下面有多个xxMixin(Vue)的调用,并把Vue当作参数传入,它们的作用都是为Vue的prototype扩展一些方法,这些方法都是Vue按功能将各个扩展分散到各个模块中去实现,而使用class是难以实现的。

全局 initGlobalAPI

Vue在整个初始化的过程中,除了给它的原型扩展方法,还会给Vue本身扩展全局的静态方法;

在Vue官网上关于全局的api在这个下main都能找到

/* @flow */

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 { observe } from 'core/observer/index'

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive
} from '../util/index'

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.
  Vue.util = {
    warn,
    extend,
    mergeOptions,
    defineReactive
  }

  Vue.set = set
  Vue.delete = del
  Vue.nextTick = nextTick

  // 2.6 explicit observable API
  Vue.observable = <T>(obj: T): T => {
    observe(obj)
    return obj
  }

  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.
  Vue.options._base = Vue

  extend(Vue.options.components, builtInComponents)

  initUse(Vue)
  initMixin(Vue)
  initExtend(Vue)
  initAssetRegisters(Vue)
}

数据驱动

Vue和react的核心思想都是数据驱动,而什么是数据驱动呢?所谓的数据驱动就是不直接操作dom,而是通过数据的修改来改变视图的状态。这样做的好处在于避免了直接操作dom,使代码更加的简洁易懂,同时避免了浏览器的重绘重排等性能的消耗,能够更快(不是说直接操作dom慢,而是这样更快)。所以当交互复杂时,只关心数据的修改使得代码的逻辑更加清晰,性能也更好。那么关于dom,vue是怎么将数据和模板渲染成dom的呢?

new Vue发生了什么

之前提到,vue的本质是一个function类,通过new来实例化。

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

从这里可以看出,Vue只能通过new来实例化,如果不是生产环境并且不在Vue原型链上,那么就会warn应该使用new 关键字;

当是通过new关键字来实例化一个对象的时候,vue会执行Vue原型链上的_init方法来初始化vue,并将节点(字符串)作为参数传入(options是new Vue('#app')时传入的字符串);在_init下会初始化生命周期、事件、render、props、data等

vm._self = vm
  initLifecycle(vm)
  initEvents(vm)
  initRender(vm)
  callHook(vm, 'beforeCreate')
  initInjections(vm) // resolve injections before data/props
  initState(vm)
  initProvide(vm) // resolve provide after data/props
  callHook(vm, 'created')

  /* istanbul ignore if */
  if (process.env.NODE_ENV !== 'production' && config.performance && mark) {
    vm._name = formatComponentName(vm, false)
    mark(endTag)
    measure(`vue ${vm._name} init`, startTag, endTag)
  }

  if (vm.$options.el) {
    vm.$mount(vm.$options.el)
  }

在最后,如果有el属性,那么就调用vm.$mount方法挂载vm,挂载vm的最终目的就是为了将模板渲染成最终的DOM;

明天计划:Vue实例挂载的实现。

相关文章

网友评论

      本文标题:vue源码第一天

      本文链接:https://www.haomeiwen.com/subject/hlopxktx.html