vue2源码刨析
手搓vue2源码地址:
gitee地址:https://gitee.com/obsessed-with-summer/vue2-source-code-analysis.git
数据监听:
代码位置:src/observer
发布者订阅者+Object.defineProperty中的get和set实现数据劫持:
ast语法树解析:
代码位置:src/compile
主要是通过这个方法生成render函数,其中包括:html解析为ast语法树,ast拼接为字符串,通过该字符串生成rende函数
function compileTofunction(el) { //1、将html变成ast语法树 let ast = parseHTML(el); //2、将ast语法树遍历拼接成字符串 let code = generate(ast); //3、将字符串变成render函数 let render = new Function(`with(this){return ${code}}`) return render }
通过_render生成虚拟dom:
代码位置:src/Vnode
_update时候,触发_renders生成新的虚拟dom,然后调用patch方法进行新旧dom对比。
patch有两个参数,分别是新旧dom:
首先进行以下判断:
- 没有新节点,直接触发旧节点的
destory
钩子 - 没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全是新建,所以只调用
createElm
- 旧节点和新节点自身一样,通过
sameVnode
判断节点是否一样,一样时,直接调用patchVnode
去处理这两个节点 - 旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点
patchVnode做了如下操作:
- 新节点是否是文本节点,如果是,则直接更新
dom
的文本内容为新节点的文本内容 - 新节点和旧节点如果都有子节点,则处理比较更新子节点
- 只有新节点有子节点,旧节点没有,那么不用比较了,所有节点都是全新的,所以直接全部新建就好了,新建是指创建出所有新
DOM
,并且添加进父节点 - 只有旧节点有子节点而新节点没有,就是把所有的旧节点删除,也就是直接把
DOM
删除
两者都有子节点,则通过updateChidren来比较:
通过双指针的方式,进行头头比较,尾部尾部比较,然后交叉比较,最终暴力对比。