Vue源码编译过程

Vue源码编译过程

一、挂载
初始化$mounted会挂载组件,不存在 render 函数时需要编译(compile);

二、compile
1.compile 分为 parse,optimize 和 generate,最终得到 render 函数;

2.parse 调用 parseHtml 方法,方法核心是利用正则解析 template 的指令,class 和 stype,得到 AST;

3.optimize 作用标记 static 静态节点,后面 patch,diff会跳过静态节点;

4.generate 是将 AST 转化为 render 函数表达式,执行 vm._render 方法将 render 表达式转化为VNode,得到 render 和 staticRenderFns 字符串;

5.vm._render 方法调用了 VNode 创建的方法createElement
// render函数表达式
(function() {
with(this){
return _c('div',{ //创建一个 div 元素
attrs:{"id":"app"} //div 添加属性 id
},[
_m(0), //静态节点 header,此处对应 staticRenderFns 数组索引为 0 的 render function
_v(" "), //空的文本节点
(message) //判断 message 是否存在
//如果存在,创建 p 元素,元素里面有文本,值为 toString(message)
?_c('p',[_v(" "+_s(message)+" ")])
//如果不存在,创建 p 元素,元素里面有文本,值为 No message.
:_c('p',[_v(" No message. ")])
]
)
}
})

三、依赖收集与监听
这部分是数据响应式系统
1.调用 observer(),作用是遍历对象属性进行双向绑定;

2.在 observer 过程中会注册Object.defineProperty的 get 方法进行依赖收集,依赖收集是将Watcher 对象的实例放入 Dep 中;

3.Object.defineProperty的 set 会调用Dep 对象的 notify 方法通知它内部所有的 Watcher 对象调用对应的 update()进行视图更新;

4.本质是发布者订阅模式的应用

四、diff 和 patch
diff 算法对比差异和调用 update更新视图:

1.patch 的 differ 是将同层的树节点进行比较,通过唯一的 key 进行区分,时间复杂度只有 O(n);

2.上面将到 set 被触发会调用 watcher 的 update()修改视图;

3.update方法里面调用patch()得到同级的VNode 变化;

4.update 方法里面调用createElm通过虚拟节点创建真实的 DOM 并插入到它的父节点中;

5.createElm实质是遍历虚拟 dom,逆向解析成真实 dom;

原文地址:https://www.cnblogs.com/guwufeiyang/p/13279445.html