乐趣区

关于vue.js:vue源码解析一

vue 源码解析

一、初始化

1.new Vue()


当咱们 new Vue({el:'#app',data:{}}) 时候,这是就要找到 Vue 的构造函数
该文件的门路为 src\core\instance\index.js



Vue 的构造函数  判断环境并且 立刻调用 this._init()办法,并把参数传入。function Vue (options) {
    判断是否为生产环境并且 查看 vue 是否在 this 的 prototype 的原型上
  // 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)
定义 $data,props,set,delete,watch, 并且 $data 和 $props 是只读属性。stateMixin(Vue)
初始化事件核心
eventsMixin(Vue)
初始化生命周期
lifecycleMixin(Vue)
初始化渲染函数
renderMixin(Vue)

export default Vue

Vue就是一个 Function 实现的类,应用必须是 new 实例,而后调用 this._init 办法

构造函数下方执行了很多办法(***MIixin(Vue)),这些办法的作用就是给 Vue 的 prototype 下面增加一些办法,这些办法是依照性能去定义的,别离在多个模块去实现。

2.this._init()的过程

  • this._init(options) 该办法是在 initMixin(Vue) 外面实现的。
  • 门路 src\core\instance\init.js
Vue: Class<Component>  指定传入参数为 class 类

export function initMixin (Vue: Class<Component>) {在 Vue 的原型下面增加_init()办法  负责 vue 的初始化过程。Vue.prototype._init = function (options?: Object) {
    获取 vue 的实例
    const vm: Component = this
    
    
    每个 vue 下面都有一个 uid
    让 vueuid 自增
    保障 vue 的唯一性
    vm._uid = uid++
    
    
    vue 实例不应该是一个响应式的,做个标记
    vm._isVue = true
    
    *****************************************************************************
    
    
    if (options && options._isComponent) {
      /**
     * 如果是子组件初始化时走这里, 这里只做了一些性能优化
     * 将组件配置对象上的一些深层次属性放到 vm.$options 选项中,以进步代码的执行效率
     */
      
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    /* istanbul ignore else */
    if (process.env.NODE_ENV !== 'production') {initProxy(vm)
    } else {vm._renderProxy = vm}
    // expose real self
    vm._self = vm
    组件关系初始化
    initLifecycle(vm)
    初始化自定义事件
    initEvents(vm)
    初始化插槽
    initRender(vm)
    调用 beforeCreate 的生命周期
    callHook(vm, 'beforeCreate')
    provide 和 reject 传值
    initInjections(vm) // resolve injections before data/props
    数据初始化  响应式原理的外围, 解决 props methods computed data watch 等
    initState(vm)
    provide 和 reject 传值
    initProvide(vm) // resolve provide after data/props
     调用 created 的生命周期
    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)
    // }
    判断数据中有没有 el,如果有,主动执行 $mount
    没有的话,就要手动去挂载。if (vm.$options.el) {vm.$mount(vm.$options.el)
    }
  }
}

3. 响应式原理 initState(vm)

  • initState 在import {initState} from './state'
  • 同级目录下找到 state.js
export function initState (vm: Component) {vm._watchers = []
  const opts = vm.$options
  解决 props 对象 为每一个 props 对象下面设置响应式
  if (opts.props) initProps(vm, opts.props)
  解决 methods
  if (opts.methods) initMethods(vm, opts.methods)
  初始化 data,if (opts.data) {initData(vm)
  } else {observe(vm._data = {}, true /* asRootData */)
  }
  解决 conputed
  if (opts.computed) initComputed(vm, opts.computed)
  解决 watch
  if (opts.watch && opts.watch !== nativeWatch) {initWatch(vm, opts.watch)
  }
}
退出移动版