一.虚拟DOM
(1).原理
(2).结构
{
tag: 'ul',//标签
attrs:{//属性
id: 'list'
},
children:[//子元素
{
tag: 'li',
attrs: {className: 'list-item'},
children: ['first item']
},
{
tag: 'li',
attrs: {className: 'list-item'},
children: ['second item']
},
]
}
(3).为什么使用虚拟DOM
如果只是更改部分元素的操作会导致没必要操作的元素也会发生改变
二.snabbdom
(1).说明
(2).使用
var container = document.getElementById("container");
var snabbdom = window.snabbdom;
//定义patch函数
var patch = snabbdom.init([
snabbdom_calss,
snabbdom_props,
snabbdom_style,
snabbdom_eventlisteners
])
//定义h函数
var h = snabbdom.h;
//生成vnode
var vnode = h("ul#list",{},[
h("li.list-item",{},"first item"),
h("li.list-item",{},"first item")
])
patch(container , vnode )//将生产元素渲染上去
无论是修改还是添加都只会渲染改变过的内容(diff算法),不会重新从头渲染
changeBtn.addEventListener("click", function(){
//重新生成Node
var vnode = h("ul#list",{},[
h("li.list-item",{},"第一个item"),
h("li.list-item",{},"seconditem"),
h("li.list-item",{},"third item"),
])
})
三.diff算法
(1).diff算法背景
更多得DIFF算法可以关注我,后面会提供vue源码解析中得diff算法源码
github中也有
(2).虚拟dom中的diff算法
//传的数据则为上方第一个代码
function createElement(vnode){
var tag = vnode.tag,
attrs = vnode.attrs|| {},
children = vnode.children ||[],
attrName;
if(!tag){
return null;
}
var elem = document.createElement(tag);
for(attrName in attrs){
if(attrs.hasOwnProperty(attrName)){
elem.setAttribute(attrName, attrs[attrName])
}
}
children.forEach(function(childVnode){
elem.appendChild(createElement(childVnode));
})
return elem
}
function updateChildren(vnode, newVnode){
var children = vnode.children || [],
newChildren = newVnode.children || [];
children.forEach(function(childVnode, index){
var newChildVnode = newChildren[index];
if(childVnode.tag === newChildVnode.tag){
updateChildren(childVnode, newChildVnode)
}else{
replaceNode(childVnode, newChildVnode);
}
})
}
function replaceNode(vnode, newVnode){
var elem = vnode.elem,
newElem = createElement(newVnode);
...
}