虚拟DOM-vue和react
虚拟dom和真实dom?
虚拟dom:
const vNode={ key=null, props:{ children:[ {type:'span'}, {type:'span'} ], className:'red', onclick:()=>{} }, ref=null, type='div' }
type用来表现标签类型,props用来表示属性。
虚拟dom缺点:需要额外的创建函数createElement,可以用jsx来简化,但是js不识别jsx语法。
虚拟dom:
js按照dom结构去实现的树形结构对象,也可以叫做dom对象。
createElement的方法时vue和react创建虚拟dom的方法,接受三个参数 type,props,children
render转化成真实dom:document.createElement()
梳理整个dom-diff的过程:
1.用js对象模拟虚拟DOM,
2.把此虚拟DOM转成真是DOM并插入到页面。
3.当有变化,比较两个虚拟DOM树的差异,得到差异对象diff,
4.把差异对象应用到真正的DOM上 (patch)
为什么有dom,还要加一层额外的抽象?
前端性能优化的一个秘诀就是 尽可能少的操作dom,dom相对较慢,且频繁操作会导致浏览器回流和重绘,尽量在patch过程 一次性将差异更新到dom上。
虚拟dom
为了解决浏览器性能问题设计出来的,出现多次更新dom的动作,虚拟dom不会立即操作,而是将更新的diff内容保存到本地js对象,最终将这个js对象一次性应用到dom树。
diff算法:
用来比较两棵虚拟dom树的差异,一般在前端当中,你很少会跨越层级地移动dom元素,所以只对同一层级元素进行对比,深度优先遍历dom树。
new vue ----init --- $mount ----- compile ---- render --- vnode --- patch (虚拟dom)-- dom
渲染函数:是用来生成虚拟dom的。vue使用模板来构建页面,底层将模板编译成渲染函数。
vNode虚拟节点: 可以代表真实的dom节点 ,通过createElement 方法将vnode渲染成真实的dom节点。
patch: 将虚拟节点渲染成真实dom,过程就是比较新旧虚拟节点的差异,将差异结果更新。
模板->渲染函数->虚拟DOM -->真实DOM树
因为操作dom慢,但是运行js速度快,因此将大量dom操作在js中运行,运用patching算法计算出真正需要更新的节点,最大限度减少操作dom,从而提升性能。
react的虚拟dom
jsx---createElement - - 虚拟DOM(js对象)-- 真实DOM
vue和react?
他们的区别不在于,双向数据绑定,双项数据绑定只是对表单而言,不过是value的单向绑定和onChange事件侦听的语法糖。
他们的区别是理念上的:vue进行数据拦截/代理,对侦测数据更敏感。
vue: 更新对象,setter变化,getter变化 触发watch,渲染 对比差异 更新
react:useState执行,render执行,生成虚拟dom,对比差异 更新
diff算法
比较两棵virtual dom树的差异,如果完全比较那么复杂度为你n^3,但是在前端中,很少跨越层级移动dom元素,所以,vdom一般进行同层级的元素比较,复杂度为n。
1、深度优先遍历,记录差异。有差异的话,记录到patch对象里边。