整理一个vue实例的产生过程: 从new Vue到mounted

3,355 阅读3分钟

前言: 去年花了几天时间尝试解读vue源码,可惜基础不够再加上项目压着,无疾而终。今年继续挑战~,let‘s go

本文算是自己学习源码的一篇整合笔记,会直接跳过很多细节,先把整体逻辑理一遍。

1.先写一个简单的demo吧

     


2.vue构造函数接收到即将要创建vm的options



找找_init

在原型链上找到了它。


3. mergeOptions整合、初始化部分属性

在接收到options之后,会先交给mergeOptions整合一遍部分属性,它负责按照预设定逻辑合并上级options(如果有)和规范prop,inject, Directives的命名。

并且它还会接受上级mixins(上级组件和全局)




4.initProxy创建proxy代理

下一步是由initProxy给实例创建proxy代理,代理的位置在vm._renderProxy






5.initLifecycle创建生命周期

这一步给vm添加很多的属性,代码上可以看到,它先给vm继承了族谱(如果有父级),

随后预定义了$refs和$children等比较眼熟的属性,这些属性在后面的阶段中都会用上,

其中比较特殊的是_isMounted和_isDestroyed等,它们主要是标记组件状态的,比如

_isDestroyed,一个已经销毁的组件自然不需要做很多操作了


6.initEvents初始化父级事件


这一步骤主要是初始化父组件添加到当前vm的事件, 就不深入了。




7.initRender创建vm渲染逻辑以及接受$attrs、$listeners和插槽


这里比较重要的是vm._c和vm.$createElement的区别只有对于render函数中children参数的处理方式,个人理解上,后者是整体渲染的时候用,前者则是只有本级dom更新渲染的时候使用。


8.beforeCreate  第一次钩子触发了


9.initInjections获取上级注入的依赖



10.初始化vm基础的常见属性:props,methods, data, computed, watch



11.initProvide 初始化依赖注入




12.created第二个钩子被触发,vm数据已经准备就绪


13.获取vm的render函数

如果options中不包含render函数,那么这时候compileToFunctions函数就要开始工作了,它的工作主要是将template模板编译成ast对象,随后该对象将被转换成独有的render函数,

列如我的第一步创建的demo,他的render函数如下:



是不是密密麻麻  看着眼睛疼。 我格式化一下:

function anonymous() {
        with(this){
          return _c(
            'div',
            {
              attrs:{"id":"app"},
              on:{"click":c}
            },
            [
              _l(
                (b),
                function(item){
                  return _c('p',
                  {
                    key:item,
                    staticClass:"ppp"
                  },
                  [_v(" "+_s(item))])
                }
              ),
              _v(" "),
              _c('p',[_v(_s(d))])
            ]
            ,2
          )
        }
      }

眼熟了吧。  是不是和平时写的render函数一个样子(其中还有一些内置函数就不说了)


14.beforeMount,render函数已就绪,可以准备渲染视图了,第三个钩子被触发


15.给vm添加监控器,以及初次渲染页面



给vm创建了一个_update的方法,绑定了render函数,在需要的时候可以内部调用从而更新视图,然后给vm添加了一个监视器,它被放在vm._watcher,并且将_update赋给了vm._watcher.getter,让监控器可以在适当的时候更新视图。

并且在第一次绑定时,_watcher手动触发了一下update,于是此时页面终于开始第一次渲染视图。


16.mounted,第四个钩子被触发,vm实例初始化全部完成。






以上就是初步整理的vm初始化大致过程,还有很多东西没有细讲,比如watch监视器如何工作,render函数具体如何更新视图等,如果还有时间就下次再整理一下。


ps: 如果有人需要我备注过的vue源码,我可以放在我的个人网站的工具箱里,请自取