Vue2.0源码学习#0

作者: 苏星河 | 来源:发表于2016-09-07 03:34 被阅读990次

近来没什么事,准备把Vue的源码通读一遍,2.0中加入了Serve-Side-Render、Virtual-Dom等新特性,看一看实现原理,顺便记录一下学习的过程,毕竟好记性不如烂笔头。

作为源码解读系列第一篇文章,先从整个框架的入口开始看吧。Vue使用了部分ES6语法,比如module机制。

import config from './config'
//加载初始全局API
import { initGlobalAPI } from './global-api/index'
//类的初始化入口
import Vue from './instance/index'

initGlobalAPI(Vue)
//在Vue类的原型上定义$isServer属性,用于判断是否支持服务端渲染
//这样在Vue实例上调用vue.$isServer就可以知道是否开启了SSR
//关于Object.defineProperty,这是一个ES5的方法,可以直接在对象上定义属性
//Vue的数据绑定机制就是用的Object.defineProperty,这也是Vue不支持IE8及以下版本的原因
//将data对象的属性转成getter和setter,具体原理见http://cn.vuejs.org/guide/reactivity.html
Object.defineProperty(Vue.prototype, '$isServer', {
  get: () => config._isServer
})
//定义Vue版本号
Vue.version = '2.0.0-rc.4'

export default Vue

以下就是config的源码

//Vue使用了Flow做静态类型检查
//Flow可以在代码运行前检查出参数、返回值、变量等类型异常
//方便我们在代码运行前进行部分debug
/* @flow */
import { no, noop } from 'shared/util'
export type Config = {
  optionMergeStrategies: { [key: string]: Function };
  silent: boolean;
  devtools: boolean;
  errorHandler: ?Function;
  ignoredElements: ?Array<string>;
  keyCodes: { [key: string]: number };
  // platform
  isReservedTag: (x?: string) => boolean;
  isUnknownElement: (x?: string) => boolean;
  getTagNamespace: (x?: string) => string | void;
  mustUseProp: (x?: string) => boolean;
  // internal
  _assetTypes: Array<string>;
  _lifecycleHooks: Array<string>;
  _maxUpdateCount: number;
  _isServer: boolean;
}
const config: Config = {
  optionMergeStrategies: Object.create(null),
  //是否显示warning,默认显示
  silent: false,
  //是否启动devtool
  devtools: process.env.NODE_ENV !== 'production',
  errorHandler: null,
  ignoredElements: null,
  keyCodes: Object.create(null),
  isReservedTag: no,
  isUnknownElement: no,
  getTagNamespace: noop,
  mustUseProp: no,
 //组件的默认类型
  _assetTypes: [
    'component',
    'directive',
    'filter'
  ],
 //定义组件的各种生命周期
  _lifecycleHooks: [
    'beforeCreate',
    'created',
    'beforeMount',
    'mounted',
    'beforeUpdate',
    'updated',
    'beforeDestroy',
    'destroyed',
    'activated',
    'deactivated'
  ],
 //规定组件在一次刷新中的最大循环更新次数
  _maxUpdateCount: 100,
  //判断全局环境是否为server
  _isServer: process.env.VUE_ENV === 'server'
}
export default config

再来看Vue实例由哪些部分构成,这部分代码在src/instance,这个文件夹下有events.js,init.js,lifecycle.js,proxy.js,render.js,state.js`等文件,可以看到,一个Vue instance由这几部分构成。为了将这些模块组织在一起,Vue使用了Mixin模式。以下是index.js的代码:

import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'

function Vue (options) {
  this._init(options)
}

initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)

export default Vue

这里的Mixin利用了每个JavaScript对象都有一个原型,通过原型可以继承更多的属性,实现Vue类上方法的重用。在每个mixin方法中,将Vue类作为参数传递进去,并在其原型上定义各种内置方法。以eventsMixin方法为例:

//为了说明,这里是其简化版
export function eventsMixin (Vue: Class<Component>) {
  //实现事件绑定的方法,将其添加到原型上
  Vue.prototype.$on = function (event: string, fn: Function): Component {
    const vm: Component = this
   //支持绑定多个事件
    ;(vm._events[event] || (vm._events[event] = [])).push(fn)
    return vm
  }

总结:

  1. Vue中大量使用Object.property,包括利用它生成访问器,实现数据绑定。
  2. Vue使用了Flow做静态类型检查,有助于提前发现bug
  3. 实现Vue类的过程中使用了Mixin这种设计模式,基于JavaScript原型继承的特性,可以方便的扩展Vue实例的功能。

参考链接:
Object.defineProperty()
Flow | A Static Type Checker For JavaScript

相关文章

网友评论

  • RockerLau:期待#1、#2...
    苏星河: @Beyond_Xiang 😂有点尴尬……准备寒假有空的话再出新的文章,谢谢关注

本文标题:Vue2.0源码学习#0

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