什么是vdom? 为何会存在Vdom?
- 用 js 模拟 DOM 结构。
- DOM变化的对比放在js层来做。
- 提高重绘性能。
真实DOM:
- item1
- item2
js模拟:
{ tag: 'ul', attrs: { id: 'list' }, children: [ { tag: 'li', attrs: { className: 'item'}, children: ['item1'] }, { tag: 'li', attrs: { className: 'item'}, children: ['item2'] } ]}复制代码
举一个栗子:
设计一个数据表格,点击按钮更改数据。
dom 操作的写法:
Document 复制代码
vdom如何应用,核心API是什么?
-
snabbdom介绍
-
核心api:
h(),patch()
先看一个栗子:
Document 复制代码
改写上面dom处理的例子:
Document 复制代码
打开控制台观察下两种方法的DOM变化时的闪烁情况,第二种方法明显优于第一种方法,只修改了变化的部分。
diff算法
为何使用diff算法,一句话来说明的话:
因为DOM操作比较昂贵,想要减少DOM的操作就必须找出必要更新的节点,而找出的过程就称为----diff算法。
模拟 patch(container, vnode);
function createElement(vnode){ var tag = vnode.tag, attrs = vnode.attrs || {}, children = vnode.children || [] if(!tag){ return null } var elem = document.createElement(tag); for(var attr in attrs){ if(attrs.hasOwnProperty(attr)){ elem.setAttribute(attr, attrs[attr]); } } children.forEach(function(children) { elem.appendChild(createElement(children)); }) return elem}复制代码
模拟patch(vnode, newVnode)
function updateChildren(vnode, newVnode){ var children = vnode.children || []; var newChildren = newVnode.children || []; children.forEach(function(child, index){ var newChild = newChildren[index]; if(!newChild){ return false } if(child.tag === newChild.tag){ updateChildren(child, newChild) }else{ replaceNode(child, newChild) } })}复制代码