恰好看到的Vue实例对象

256 阅读3分钟

使用Vue也有一些时间了,发现对Vue的理解基本上还停留在使用层面,深究到细节处,都是似懂非懂。参考官网和网上几篇介绍Vue响应式原理的文章似乎都过于‘深入浅出’,对于我这种非计算专业毕业的同学来说,刚开始看还是比较吃力的,想继续学习研究又很难有突破,所以还是自己动手,这几天重新看了下Vue代码,对基础做些梳理,想把自己的理解写下来,也算是对自己学习的一个总结,能跟其他同学分享也是极高兴的,有理解不到位的地方,请加大多多指教。

个人觉得不管入手Vue还是其他库,最重要的是要理解好基础对象,毕竟面向对象编程嘛-_-,其中Vue构造函数,Vue实例对象,Watcher,Dep 一套下来是理解响应式的基础吧。

今天梳理的是Vue的实例对象,也就是new Vue(options)返回的对象,在实际开发中就是我们面对的应用或者组件。刚开始看代码的同学应该都有一种感觉,好像一些属性都眼熟,但是干什么用的,怎么来的不太清晰,下面列出的是Vue实例对象的属性:

const VueInstance = {
  $attrs: {},
  $children: [],
  $createElement: ƒ (a, b, c, d),
  $el: domNode,
  $listeners: {},
  $options: {},
  $parent: undefined, 
  $refs: {},
  $root: {},
  $scopedSlots: {},
  $slots: {},
  $vnode: undefined,
  $data: {},
  $isServer: false,
  $props: undefined,
  $ssrContext: undefined,
  _c: ƒ (a, b, c, d),
  _computedWatchers: {xxx: Watcher},
  _data: {__ob__: Observer},
  _directInactive: false,
  _events: {},
  _hasHookEvent: false,
  _inactive: null,
  _isBeingDestroyed: false,
  _isDestroyed: false,
  _isMounted: true, 
  _isVue: true,
  _renderProxy: {},
  _self: {},
  _staticTrees: null,
  _uid: 0,
  _vnode: {},
  _watcher: {},
  _watchers:  [] 
}

对上面的属性做个介绍:

  • _watcher: 组件模版的watcher

    • 初始化为null
    • 组件在挂载时,为组件模版实例化了Watcher实例,并赋值给vm._watcher(仅在为模版创建Watcher实例时)
  • _watchers:

    • initComputed过程中,实例化了Watcher实例,并push到vm._watchers数组中,
    • initWatch过程中,实例化了Watcher实例,并push到vm._watchers数组中,(实质上是调用vm.$watch,通过vm.$watch实例化了Watcher实例)
    • 通过vm.$watch监听的属性,实例化了Watcher实例,并push到vm._watchers数组中,包括initWatch和手动this.$watch
    • 组件在挂载时,为组件模版实例化了Watcher实例,并push到vm._watchers数组中,此处还为vm._watcher赋值(仅在为模版创建Watcher实例时)
  • _computedWatchers:

    • 实例化时,在initState中调用initComputed,为$options.computed对象中的键值对创建Watcher实例对象
    • initComputed过程中,通过defineComputed为组件实例设置对应属性,
    • initComputed过程中,实例化了Watcher实例,并push到vm._watchers数组中,
  • $options:

    • 实例化时,通过mergeOptions,合并了constructor的$options和传入配置项options。
    • $options._parentListeners属性作为组件的初始化事件
    • options.parentListeners属性也作为组件的options._parentListeners属性也作为组件的listeners属性,并且不可修改
  • $vnode: 指向$options._parentVnode

    • 在父组件中表示当前组件的vnode
    • $vnode.context,表示该组件所在父组件中的上下文,作为slotsslots和scopedSlots的上下文使用
    • $vnode.data,表示该组件所在父组件中解析到的data对象,取其中的attrs属性,设置该组件的$attrs,并不可修改。
  • _vnode:

    • 组件内模版解析后的vnode根节点,初始化为null,在挂载生命周期调用_update方法时设置
    • vnode.parent属性指向$options._parentVnode,亦等于$vnode
  • $parent:

    • 实例化时,通过options.parent向上递归查询,查找到的第一个非抽象的实例对象,如果没有那该组件就是root对象了。
  • $children:

    • 实例化时,子组件通过查找$parent对象过程,主动push。
  • root:实例化时,通过initLifecycle,查找到root: 实例化时,通过initLifecycle,查找到parent对象,取parent.parent.root对象,如果没有合适的prarent对象,那当前组件即作为prarent对象,那当前组件即作为root

  • $attrs:

    • 实例化时,通过initRender,取$vnode.data属性
    • 不可修改属性;
  • $listeners:

    • 实例化时,通过initRender,取$options._parentListeners
    • 不可修改属性;
  • $refs:

    • 初始化为空对象:{}
    • 在自建初始化时进行填充
  • $slots:

    • 初始化组件时,通过initRender,从$options._renderChildren中解析出所有对应name的slot
    • 这里的$options._renderChildren 对应组件模版中的插槽,原生标签不会有组件初始化过程
  • $scopedSlots:

    • 初始化组件时,通过initRender,初始化为空对象
  • $data:

    • 脚本库运行时,通过stateMixin,在原型上设置了$data,其get属性返回this._data
  • $props: todo

    • 脚本库运行时,通过stateMixin,在原型上设置了$props,其get属性返回this._props
  • _data:

    • 实例化时,通过initState => initData 取options.data或取options.data或取options.data执行返回的对象,并设置响应式
  • _provided:

    • 如果$options.provide有值,创建_provided对象
    • _provided对象供子元素向上遍历,查找inject时使用
  • _events:

    • 初始化为空对象:{}
    • 实例化时,如果解析后的$options._parentListeners数组不为空,则添加这些事件
    • 通过this.$on添加事件,构建{eventName: fn[]} 对象
    • 添加事件时,如果事件名以hook:开头,则设置_hasHookEvent为true
    • 通过this.$off注销事件,
  • _hasHookEvent:

    • 是否有钩子事件,初始化为false
    • 添加事件时,如果事件名以hook:开头,则设置_hasHookEvent为true
  • _staticTrees:

    • 使用v-once指令时保存的静态树,初始化为null
    • 静态的根节点时保存的静态树,为了优化
  • $el: 根节点用于挂载的元素或元素查询字符串,非必须

  • $isServer: 是否是服务端渲染

  • $ssrContext: 服务端渲染时的上下文

  • _uid: 实例化时设置,一个根据实例化Vue组件次数递增的数字,标示组件的id。

  • _isVue: 实例化时设置,作为标示

  • _self: 实例化时设置为自身的一个引用

  • _c, $createElement: 创建元素的方法

  • _renderProxy: 实例化时,生产环境下设置为自身。

  • _isMounted: 初始化为false,组件挂载后设置为true;

  • _isBeingDestroyed: 初始化为false,组件正在销毁时设置为true;

  • _isDestroyed: 初始化为false,组件销毁后设置为true;

  • _directInactive: 初始化为false

  • _inactive: 初始化为null

方法部分比较好理解就不赘述了

以上!