Vue(一)
new Vue
new Vue1. 当我们 new Vue 的时候,会执行 _init 方法。
_init2. _init 方法再原型上(中间省略 n 多代码)
_init方法执行 $mount3. $mount 方法挂载 vm,$mount 在很多文件都有定义,因为 $mount 跟 所在的平台有关系,这里我们看的是 src/platform/web/entry-runtimewith-compiler.js
注意: 如果没有定义 render 方法,则会把 el 或者 template 字符串转换成 render 方法,,所有 Vue 的组件的渲染最终都需要 render 方法。
$mount4. $mount
还是执行 $mount,接受上面传递的两个参数,第一个参数 el,它表示挂载的元素,可以是字符串,也可以是 DOM 对象,第二个参数浏览器上忽略。
$mount5. moutComponent
在 moutComponent 中 我们调用了 updateComponent
执行 vm._update(vm._render(), hydrating)
moutComponent6. _render
_render 方法执行了 render 方法并传入 参数 vm.$createElement, render = vm.$options.render
_render在官网的例子中, 使用 render 代替模板语法,它的第一个参数 createElement 就是我们的 vm.$createElement
render函数render 函数又执行了 createElement
createElementvm._render 通过执⾏ createElement ⽅法并返回的是 vnode
7. createElement
返回 vnode
_createElement ⽅法有 5 个参数, 就是我们经常手写的 render 函数,context 表⽰ VNode 的上下文环境,它是 Component 类型; tag 标签,它可以是⼀个字符串,也可以是⼀个 Component ; data 是 VNode 的数 据; children 是 VNode 的⼦节点,它是任意类型的; normalizationType 是子节点规范的类型,类型不同规范的方法也就不⼀样,它主要是参 考 render 函数是编译⽣成的还是⽤户⼿写的。
createElement8. 再回到 第5步的 _update
vm._update(vm._render(), hydrating), _render() 返回了 vnode,接着 执行 _update,_update 是实例的⼀个私有⽅法,它被调用的时机有 2 个,⼀个是首次渲染,⼀个是数据更 新的时候。 _update 的核新就是调用 vm.__patch__ 方法。
__patch__浏览器环境下 Vue.prototype.__patch__ = inBrowser ? patch : noop
var patch = createPatchFunction({
nodeOps: nodeOps,
modules: modules
});
patch 就是 createPatchFunction 的返回值, 它返回了另外一个 patch 函数,,这个方法就 赋值给了 vm._update 函数⾥调⽤的 vm.__patch__ 。
patch 方法本⾝,它接收 4个参数, oldVnode 表示旧的 VNode 节点,它也可以不存在或者是 ⼀个 DOM 对象; vnode 表示执行 _render 后返回的 VNode 的节点; hydrating 表示是否是服务端渲染; removeOnly 是给 transition-group 用的
createPatchFunction在函数中调用 createElm, createElm 的作用是通过虚拟节点创建真实的 DOM 并插⼊到它的父节点中。如果 vnode 节点如果不包含 tag ,则它有可能是⼀个注释或者纯⽂本节 点,可以直接插⼊到⽗元素中。就是最后一个 else 逻辑:
vnode.elm = nodeOps.createTextNode(vnode.text);
insert(parentElm, vnode.elm, refElm);
createElmcreateChildren 方法去创建子元素
createChildreninsert ⽅法把 DOM 插⼊到⽗节点中,因为是递归调用,子元素会优先调用insert , 所以整个 vnode 树节点的插⼊顺序是先⼦后父。
insertnodeOps 就是一些原生的 DOM 操作,比如 insertBefore, appendChild, 在 src/platforms/web/runtime/node-ops.js 中。
首次渲染我们调用了 createElm 方法,这⾥传入的 parentElm 是 oldVnode.elm 的父元素, 比如 一般我们都是使用 id 为 #app div 的父元素,也就是 Body;实际上整个过 程就是递归创建了⼀个完整的 DOM 树并插入到 Body 上。
大概流程