Vue源码解析准备篇

最近利用空闲时间又翻看了一遍Vue的源码,只不过这次不同的是看了Flow版本的源码。说来惭愧,最早看的第一遍时对Flow不了解,因此阅读的是打包之后的vue文件,大家可以想象这过程的痛苦,没有类型的支持,看代码时摸索了很长时间,所以我们这次对Vue源码的剖析是Flow版本的源码,也就是从Github上下载下来的源码中src目录下的代码。不过,在分析之前,我想先说说阅读Vue源码所需要的一些知识点,掌握这些知识点之后,相信再阅读源码会较为轻松。

前置知识点
Vue源码解析准备篇


function sum(a: number, b:number) {
return a + b;
}

export function renderList (
  val: any,
  render: (
    val: any,
    keyOrIndex: string | number,
    index?: number
  ) => VNode
): ?Array<VNode>{
...
}
val是any代表可以传入的类型是任何类型, keyOrIndex是string|number类型,
代表要不是string类型,要不是number,不能是别的;index?:number这个我们想想
正则表达式中?的含义---0个或者1个,这里其实意义也是一致的,但是要注意?的
位置是在冒号之前还是冒号之后--因为这两种可能性都有,上面代码中问号是跟在冒
号前面,代表index可以不传,但是传的话一定要传入数字类型;如果问号是在冒号
后面的话,则代表这个参数必须要传递,但是可以是数字类型也可以是空。这样是
不是顿时感觉严谨多了?同时,代码意义更明确了。为啥这么说呢? 之前看打包后
的vue源码,其中看到观察者模式实现时由于没有类型十分难看懂,但是看了这个
Flow版本的源码,感觉容易懂
 原型与原型继承
涉及到父子组件了。组件其实初始化过程都是一样的,显然有些方法是可以继承的。
Vue代码中是使用原型继承的方式实现父子组件共享初始化代码的
Object.defineProperty
这个方法在js中十分强大,Vue正是使用了它实现了响应式数据功能。
我们先瞄一眼Vue中定义响应式数据的代码
export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: ?Function,
  shallow?: boolean
) {
  .....
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
          if (Array.isArray(value)) {
            dependArray(value)
          }
        }
      }
      return value
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val
      /* eslint-disable no-self-compare */
      if (newVal === value || (newVal !== newVal && value !
      == value)) 
      {
        return
      }
      /* eslint-enable no-self-compare */
      if (process.env.NODE_ENV !== 'production' && customSetter) 
      {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = !shallow && observe(newVal)
      dep.notify()
    }
  })
}

其中我们看到Object.defineProperty这个函数的运用,其中第一个参数代表要设置的对象,第二个参数代表要设置的对象的键值,第三个参数是一个配置对象,对象里面可以设置参数如下:
value: 对应key的值,无需多言
configurable:是否可以删除该key或者重新配置该key
enumerable:是否可以遍历该key
writable:是否可以修改该key
get: 获取该key值时调用的函数
set: 设置该key值时调用的函数
我们通过一个例子来了解一下这些属性

let x = {}
 x['name'] = 'vue'
 console.log(Object.getOwnPropertyDescriptor(x,'name'))
打印结果如下:

{
    value: "vue",
    writable: true, 
    enumerable: true, 
    configurable: true
}
上一篇:建库和表的脚本.sql


下一篇:Java EE业务处理流程与XML的引入