首先我们进行编译,在内存中会生成虚拟的dom树;然后将内存中的虚拟dom树初始化渲染成真实的dom树;而当我们修改数据的时候,会将之前的虚拟dom树结合新的数据生成另一新的虚拟dom树;并将生成好的新的虚拟dom树与上一次的虚拟dom树结构进行对比(diff算法),找出真正需要更新的数据进行真实的dom操作
- 真实DOM
一个真实的dom:
- 虚拟DOM
虚拟dom(Virtual DOM) 可理解为一个简单的JS对象,并且最少包含标签名( tag)、属性(attrs)和子元素对象( children)三个属性。属于内存数据,是真实dom的一层映射。
下面是一个模拟的虚拟dom:
var vDom={
tag:"div",
attr:{
id:"box"
},
children:[
{tag:"span",content:9},
{tag:"ul",attr:{className:"list"}}
]
}
- diff算法
diff算法的作用是用来计算出虚拟DOM( Virtual DOM )中被改变的部分,然后针对该部分进行原生DOM操作,而不用重新渲染整个页面。
diff算法是层级比较,如上图
在进行比较的时候,是一层一层的进行
如果都是同一类型的组件,不必做出反应,而是继续比较Virtual DOM树
如果出现不是同一类型的组件,则替换整个组件下的所有子节点
部分代码:
//old虚拟dom
var vDom = {
tag: "div",
attr: {
id: "box"
},
children: [
{ tag: "span", content: 9 },
{ tag: "ul", attr: { className: "list" } }
]
}
//修改数据
data.arr.push("<li>99</li>")
//new虚拟dom
var vDom = {
tag: "div",
attr: {
id: "box"
},
children: [
{ tag: "span", content: 9 },
{
tag: "ul", attr: { className: "list" }, children: [
{ tag: "li", content: "99" },
]
}
]
}
在修改了数据之后,之前的old虚拟dom树与修改的数据结合生成新的new虚拟dom树,
然后diff算法比较前后old虚拟dom树和new虚拟dom树的区别,最后发现区别在于new
虚拟树{tag:"li",content:"99"}的添加,然后仅针对有区别的数据进行dom操作渲染,
而不是从新渲染整个
- 目的
当内部数据变化,生成新的虚拟dom树,与之前的虚拟dom树结构进行对比。也就是说,当数据变化的时候,大量操作的是虚拟dom,而虚拟dom属于内存数据,操作起来性能要高的多。而真实的dom操作,只有在追加的那一刻才会进行操作,大大提升了性能。