(该文章对src/core/instance下的文件的代码功能做了注解,便于大家在看源码过程中快速理解)
入口文件 src/core/instance/index.js 中可以看到
vue的构造函数在此, 然后通过mixin的方式将
数据方法等特性处理(state)
事件处理(events)
生命周期(lifecycle)
渲染函数(render)
的相关的方法挂到vue的原型上去。
挂上了_init 方法,没错就是 构造函数当中调用的_init方法。
这里做了一些参数处理,其中作者在参数对象赋值的时候,用一个个赋值代替列举赋值来提升性能。 这样注释的: // doing this because it's faster than dynamic enumeration.
然后就是依次执行以下方法,包括各个init函数和触发钩子
initstate一共做了如下操作
initprops和initdata的处理类似:
initprops做了类型检验,做了definereactive就是响应式处理;
initdata做了函数处理(data是对象或者函数),然后检查key是否与props重复,还检查了key是否$ 或者 _ 开头,这是vue内部使用, 如果你的key以此开头,你就会拿不到你的key了(这个好像没看到说明,感觉可以提示下)
然后做了个proxy,把用户参数props和data分别代理到 _props 和 _data 这2个内部属性,用户访问其实访问到了_props和_data下。
initmethods 这个就是把methods内部的函数bind到实例然后挂到实例
initwatch 通过遍历然后执行$watch方法来处理
initcomputed 遍历为创建一个 watcher 实例,然后放到_computedwatchers
(响应式相关后续再展开)
statemixin 混入方法挂了$data,$props,$set,$delete等让数据操作指向_data 和 _props,然后挂了$watch 方法
挂载$on,$once,$off,$emit 四个方法
事件句柄都保存在 _events 这个属性里,在$on方法里做了个处理,判断该实例是否有使用生命周期的hook,如果没有_hashookevent这个值是false,然后在lifecycle的callhook方法里将不会$emit生命周期hook,是一个性能优化。
在原型上挂上 _mount 方法,这个比较重要, $mount 用的就是方法, ($mount在上面的init函数被调用)这个方法运行的时候需要用到render函数里了,没有会报错(关于这点,vue会把template或者el里的html模版最终转成render函数,一般如果我们用vue-loader开发,已经把template里的内容转成了render函数,所以最后打包出来的不会含有转化template的功能代码),render函数返回的是一个vnode,下面贴个_mount部分代码:
这里可以看到2个生命周期了
_update 方法开始去做dom更新了,看_update方法
一开始用_ismounted判断是否触发beforeupdate钩子,因为第一次插入dom也是调用这个方法,但是不应该触发beforeupdate
然后就去调用 patch 方法去做diff 然后更新dom了。(vnode以后再看)
另外,还挂载了$forceupdate和$destroy 这2个方法
先挂载了 $nexttick 方法.
然后在rendermixin函数内往原型挂载了_render 方法(在instancei 下有个render-helpers文件夹里面有处理render相关的工具函数供调用)这个方法做了slot相关的操作,然后调用render函数拿到vnode ( render 相关的需要具体展开)
这里有个_renderproxy ,在非生产环境下做了proxy,看 proxy.js ,就是在访问实例属性的时候,访问不存在的属性的时候给予提示.
以上。