3分钟说明vue从$mount开始做了什么,如何递归

177 阅读1分钟

$mount:把template字符串搞成真实dom的过程。关键1编译的时候碰到自定义组件怎么处理?关键2虚拟dom转换真实dom的时候碰到自定义组件又是怎么处理?本文关注的是vue处理组件的时刻,从Vue.$mount() debug进去,自上而下捋通处理组件的一个绝对流程

  1. 根组件 $mount()
  2. 如果没有写render属性,则 compileToFunctions 编译出render函数
  • 编译会根据template字符串,parse生成 ast 树状结构对象
  • generate生成render函数字符串(这个过程处理了v-if、v-for等标签从逻辑上是如何影响dom结构和数量的),最后new Function得到render函数
  1. 根组件 new Watcher

  2. updateComponent 众所周知的beforeMount、mounted在这个方法中先后调用

  3. 执行render() 得到根组件虚拟dom 

  • render中的_c 即h 即createElement,当传入_c的是自定义组件的标签,会调用createComponent,为该组件准备好init方法以及构造方法,注意只是准备,不是执行,并为该组件标签生成一个vnode返回
  1. _update(根组件vnode)

  2. patch

  3. createEl  虚拟dom转换为真实dom的方法

  • 因为vnode是一颗树,所以会向下递归调用createEl,但要注意这里只是html标签的递归
  • 所以说,vnode并不是组件树哦,充其量只是描述一个个组件页面的html标签树,因为vnode对象本身并没有向下用继续用vnode描述组件内部内容的能力
  1. 如果传入createEl的vnode是自定义组件,于是调用createComponent
  2. 这个自定义组件标记为child,然后init
  • child实例化 构造函数就是在前面执行render的时候准备好的
  • child.$mount()
  • 终于,回到梦开始的地方,现在才是真正意义上,开始了组件递归 👉
  • 如果child没有写render属性, compileToFunctions
  • child new watcher
  • ...
  1. 最后child完成实例化和$mount(),才会把自己insert()插入到dom 然后继续走父组件$mount剩下的代码

ps:上面是进入方法内部的意思

刚开始学习vue2,记录以上过程,旨在建立一个对Vue自上而下挂载的本质认识,并且足够精简,但不讨论细节,如有不对希望大佬勘误