# DOM and diff **Repository Path**: chenluchao/dom-diff ## Basic Information - **Project Name**: DOM and diff - **Description**: 虚拟DOM与diff算法源码学习 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-08-17 - **Last Updated**: 2021-08-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: 源码-diff, snabbdom, Vue ## README # 学习记录引导-snabbdom ## 基础环境搭建 * 在文件夹下创建身份证:`npm init` * 安装snabbdom:`npm i -S snabbdom` * 安装webpack webpack-cli webpack-dev-server:`npm i -D webpack@5 webpack-cli@3 webpack-dev-server@3` * 配置webpack基本配置 * 创建文件webpack.config.js * 创建www/index.html展示页面 * 创建入口文件src/index.js * 修改package.json中启动命令为:`"dev": "webpack-dev-server"` * 修改src/index.js文件运行demo检查是否正常运行 ## 虚拟DOM和h函数 * 虚拟DOM:用JavaScript对象描述DOM的层次结构。DOM中的一切属性都在虚拟DOM中有对应的属性 * h函数:可以嵌套,嵌套数组,或单个元素都可以 ```javascript const myVnode3 = h('ul',[ h('li','苹果'), h('li',[ h('span',{class:{'li':true}},'榴莲'), h('span',{class:{'li':true}},'火龙果') ]), h('li',h('span','香蕉'),), ]) ``` ## diff比较算法 ```javascript patch函数被调用 | oldVnode是虚拟节点还是DOM节点-->是DOM节点->将oldVnode包装为虚拟节点 | | 虚拟节点 ----------------------------- | | oldVnode和newVnode -->不是-->暴力删除旧的,插入新的 是不是同一个节点? | 是 | ------精细化比较------- | oldVnode和newVnode 是不是内存中的同一个对象----是--->什么都不做 | 不是 | newVnode有没有text属性------有----->oldVnode和newVnode是否相同 | | | | 相同 不同 | | | 没有 什么都不做 把elm中的innerText改变为newVnode的text (newVnode有children) (即使oldVnode有child属性而没有text属性,那么也没事 | innerText一旦改变为新的text老children就没了) | oldVnode有没有子节点----------------有**----------->新老节点都有children | 此时要进行优雅的diff 没有(意味oldVnode有text) | | 四种判定 1、清空oldVnode中text | 2、把newVnode中children添加到DOM中 四判定还有剩余项怎么办 ---------------如果新节点先循环完毕, | 如果老节点中还有剩余节点, | 说明老节点中剩余的节点是需要删除的节点 | 如果旧节点先循环完毕, 说明新节点中有要插入的节点 ``` * 判断是不是同一个节点:旧节点的key要和新节点的key相同且旧节点的选择器要和新节点的选择器相同 * 创建子节点时,所有需要递归创建出来的 ## diff算法的子节点更新策略 1. diff算法优先策略——四种命中查找 * 新前与旧前 * 新后与旧后 * 新后与旧前 * 新前与旧后 * 以上四种命中一种就不会再进行命中判断了,如果都没有命中那么需要循环旧节点查找,将查找到的节点的真是DOM插入到旧前之前 * 如果旧节点先循环完毕,说明新节点中有要插入的节点 * 如果新节点先循环完毕,如果老节点中还有剩余节点,说明老节点中剩余的节点是需要删除的节点 * ①当新前与旧前匹配到则更新这个节点 * ②当新后与旧后匹配到则更新这个节点 * ③当新后与旧前匹配,此时要移动节点,移动新后指向的这个节点到老节点的旧后的后面 * ④当新前与旧后匹配,此时要移动节点,移动新前指向的这个节点到老节点的旧前的前面