Vue状态初始化源码探究

原创 Fly丶 教程 vue专题 81阅读 2018-12-09 11:36:14 举报

这里的状态初始化指的就是在创建实例的时候,在配置对象里定义的属性、数据变量、方法等是如何进行初始处理的。由于随后的数据更新变动都交给观察系统来负责,所以在事先弄明白了数据绑定的原理之后,就只需要将目光集中在这一部分。

来仔细看看在核心类中首先执行的关于 state 部分的源码:

initState

这段代码非常直白,主要用来执行配置对象里定义的了状态的初始化。这里分别有 props、data、methods、computed、watch 五个配置对象,分别有各自的初始化方法。在仔细研究它们的具体实现之前,先来看一段将在各个初始化函数里用到的辅助函数。

proxy 函数的定义非常重要,在下面要探究的各个初始化函数中它,它会将我们在配置对象中设置的属性全部定义到实例对象中,但是我们对这些属性的操作是通过各部分相应的代理属性上来执行的。get 和 set 方法的实现非常明白的表示出这一过程,然后再将属性定义到实例中。由这个函数作为基础,继续来看看其他五个状态的初始化函数的内容。

initProps

initProps 函数的最主要内容有两点,一是对定义的数据建立观察,二是对数据进行代理,这就是私有变量 _props 的作用,之后获取和设置的变量都是作为 _props 的属性被操作。

另外初始化 props 的过程中有针对 extend 方法会使用到的 propsData 属性的初始化。具体使用是在扩展对象时定义一些 props,然后在创建实例的过程中传入 propsData 配置对象,扩展对象里相应的props属性会接收 propsData 传入的值。与在父组件传入 props 的值类似,只是这里要显式的通过 propsData 配置对象来传入值。

initData

与 props 的处理类似,initData 函数的作用也是为了对数据建立观察的依赖关系,并且代理数据到私有变量 _data 上,另外包括了对 data 与其他配置对象属性的键名冲突的检测。

initComputed

计算属性的初始化相对复杂一些,首先要对计算属性建立观察,然后再在实例上重新定义计算属性,并且执行属性代理。由于加入了服务器渲染的功能,在定义计算属性的时候对使用环境做判断,是非服务器渲染会影响到计算属性的定义,这是由于服务器渲染下使用框架时,计算属性是不提供 setter 的;另外也要根据用户定义的值是函数或者对象来对计算属性重新定义 getter 和 setter。从这段代码里可以看出一个非常重要的程序,即在获取计算属性的时候才去计算它的值,这正是懒加载的实现。

initMethods

initMethods 函数非常简单,除了一大段在非生产环境里报告检查冲突的代码,唯一的内容就是在实例上定义相应的方法并且把上下文绑定到实例对象上,这样即便不是使用箭头函数,在方法内也默认用 this 指代了实例对象。

initWatch

initWatcher 为传入的观察对象创建监视器,比较简单。值得注意的是参数的传入类型,观察对象 expOrFn 可以有两种方式,一种是字符串,一种是函数,在 Watcher 类中对此参数进行了检测,而在初始化的函数里不对它做任何处理。handler 对象也可以接受对象或字符串类型,在代码中对这两种传入方式做判断,最终找到handler引用的函数传入 $watch。

stateMixin

探索完了 initState 函数之后,继续来看看 state 混入的方法 stateMixin,在这个函数里会提供上面还未曾提到的 $watch 方法的具体实现:

stateMixin执行的是关于状态观察的一系列方法的混入,主要是三个方面:

  • 定义实例 $data$props 属性的存取器
  • 定义实例的$set$delete 方法,具体实在定义在观察者模块中
  • 定义实例的 $watch方法
    到这里,关于状态初始化的部分就探索完毕了,接下来要继续研究另一个与开发过程紧密关联的部分——虚拟节点和模板渲染。

状态初始化是与我们在开发的时候最息息相关的部分,在创建实例对象的配置对象中,我们设置了这些属性和方法,实例初始化的过程中对这些传入的配置进行了很多预先的处理,这就是状态初始化背后的逻辑。在探索到这一部分的时候才真正的感到,终于与平时的开发关联起来了。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复