这里选用的是runtime and compile版本的vue,首先用mount
变量缓存起来Vue的原型上挂载的$mount
方法,然后又重新定义了$mount
方法。这个$mount
方法其实是在引入的./runtime/index
文件中定义的,为什么要重新定义一遍,因为runtime only 版本是没有这个逻辑的,实际上是给runtime only版本用的
当在初始化执行vm.$mount(vm.$options.el)
挂载的时候,实际上调用的重写后的$mount函数,这个函数首先对el
参数做了一个处理,el
可以是一个字符串也可以是一个element
,这里调用了query方法
query方法实际上调用了原生的api,如果el
是一个字符串,就调用querySelector
方法,如果找不到的话,就会报一个错,返回一个空的div,否则不是字符串,已经是一个dom对象 ,那就直接return就可以了
拿到el
之后,这里已经被转成的dom对象,,然后又做了一个简单的判断el
如果是一个body或这是一个文档元素就会报一个错,Vue不能直接挂载到html和body上,因为它是会覆盖的,如果挂载的话会把整个body覆盖,整个html就不对
然后拿到options
,然后判断有没有手写render
方法 ,然后判断有没有用到template
,如果有template
就会做一些处理。如果template
是一个dom
对象的话就会拿到innerHTML
的内容,否则就会警告没有定义这个template
。
如果没有定义template,就会调用getOuterHTML
方法
这个方法拿到dom对象的outerHTML,直接返回,如果没有就在外面包一层div再返回,实际上是outerHTML的polyfill的调用。这样就拿到了返回的dom字符串。
最后就是编译,调用compileToFunctions
拿到生成的render
函数以及静态render函数staticRenderFns
。
最终Vue只认render函数,如果没有render函数,就转换成编译的模版。如果有render函数,就直接返回mount
方法的调用
然后在index.js中执行mountComponent
方法,
首先用vm.$el
缓存el
的值,然后判断有没有render函数,没有render函数就创建一个空的vnode
,如果有template
但是template
不是以#
开头就会报警告(用的runtime only
版本,但是没有写render
函数)
然后定义了一个updateComponent
,这个其实是一个与Vue性能埋点有关的函数
最终调用了vm._update(vm._render(), hydrating)
,第一个参数是通过vm._render
渲染出一个vnode
接下来调用了 new Watcher
这是一个渲染Watcher
,执行Watcher
的构造,关键是判断expOrmFn
是不是一个函数,如果是一个函数就会给getter
赋值这个函数,否则调用parsePath
方法把它转化成getter
,之后调用了this.get()
方法,关于依赖收集的,
在里面执行了getter
方法,那实际上就是执行了updateComponent
方法,那么就会执行vm._update
以及vm._render
,这两个函数就是最总我们要挂载在dom要用到的函数,
首先vm._render会渲染出一个vnode,然后vm._update就会传入vnode在生命周期中执行后续操作。