虚拟 DOM 是什么
虚拟DOM是一颗以JavaScript对象(node节点)作为基础的树,用对象属性来描述节点,他是对真实DOM的抽象,通过一些列操作使这棵树映射到真实环境上
虚拟dom就是能代表DOM树的对象,通常含有标签名,标签上的属性,事件监听和子元素们以及其它属性
虚拟 DOM 的优点
01 减少DOM的操作
虚拟dom可以将多次操作合并为一次操作,减少DOM操作的次数。比如你添加1000个节点,确实一个接一个操作, 虚拟DOM借助DOM diff可以把多余的操作省掉,减少DOM操作的范围。比如你添加1000个节点,其实只有10个是新增的
02 跨平台渲染
虚拟DOM不仅可以变成DOM,还可以变成小程序、 iOS应用、安卓应用,因为虚拟DOM本质上只是一个JS对象
虚拟 DOM 的缺点
需要额外的创建函数,如create Element或h,但是可以通过JSX来简化成XML写法
DOM diff
- DOM diff是一个函数,称之为 patch
- patches = patch(oldVNode, newVNode)
- patches 就是要运行的DOM操作
DOM diff 是两个虚拟 DOM 树对比的算法:diff 算法仅在两个树的同级的虚拟节点之间做比较,递归地进行比较,最终实现整个 DOM 树的更新。
用 JS 对象的方式来表示 DOM 树的结构,然后根据这个对象构建出真实的 DOM 树,插到文档中 当状态变化的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树的差异 最后把所记录的差异应用到所构建的真正的DOM树上,进行视图更新
diff算法的三个步骤(大致逻辑):
- 用 JS 对象的方式来表示 DOM 树的结构,然后根据这个对象构建出真实的 DOM 树,插到文档中
- 当状态变化的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树的差异
- 最后把所记录的差异应用到所构建的真正的DOM树上,进行视图更新
DOM diff 在做比较时分为了三个层级
- Tree Diff(层级比较)
- 先进行树结构的层级比较,对同一个父节点下的所有子节点进行比较;
- 接着看节点是什么类型的,是组件就做 Component Diff;
- 如果节点是标签或者元素,就做 Element Diff;
- omponent Diff (组件比较)
- 若组件类型相同,则继续按照层级比较其虚拟 DOM的结构;
- 如果组件类型不同,则替换整个组件的所有内容
- Element Diff (元素比较)
- 如果节点是原生标签,则看标签名做比较是否相同来决定替换还是更新属性
- 然后进入标签后代递归 Tree Diff
DOM diff 的优点
DOM diff算法可以排除多余的DOM操作。DOM diff会对比前后两次DOM树的区别,然后只更新有变化的DOM节点,优化操作。
DOM diff 的问题(key)
同级比较会出现bug。 diff算法是从左往右进行同层级对比的,如果发现元素相同但是内容不相同,会直接修改内容。这会导致有时删除了一个节点,结果却是另外一个节点被删除了。 这个问题可以通过给每一个列表指定key值来解决,注意这里的key值不能指定为index,否则无效。