虚拟dom与diff算法
以下为自己总结内容,欢迎其他程序员小伙伴一起交流谈论!
1、概念引入
- 大量的dom操作会使性能降低,而且花费的时间更多,为此,为了减少dom操作,提高性能,我们应该先操作数据,再去操作dom,因此,前端引入了虚拟dom,即vdom
- Vue是一种MVVM框架,Vue高性能的原因之一就是vdom
2、什么是虚拟dom(vdom)
-
它是一个Object对象模型,用来模拟真实dom节点的结构
-
问题:vdom如何模拟真实dom?这里有个需求:将来我想在div中增加一个li,里面的内容为 : hello
一般代码操作示例:
<div class = "box">
<ul>
<li> 你好 </li>
</ul>
</div>
var list = document.querySelector( '.list' )
var li = document.createElement( 'LI' )
li.innerHTML = ' hello '
list.appendChild( li )
- vdom解决问题的代码操作使用流程
1、获取数据
var data = {
id: 1,
name: '你好'
}
2、创建vdom
var vdom = {
tag: 'div',
attr: {
className: 'box'
},
content: [
{
tag: 'ul',
content: [
{
tag: 'li',
content: data.name
}
]
}
]
}
3、初次渲染 vdom(将vdom渲染成真是dom)
var div = document.createElement('DIV')
div.className = 'box'
var ul = document.createElement('UL')
var li = document.createElement('LI')
**产生的问题:**因为我们的网页结构是很复杂的,我们使用上述vdom方法去模拟dom结构,发现vdom这个对象模型会写很多,代码极其冗余,所以想如果能在js中书写dom标签结构就方便许多,所以结合了javascript + xml 弄出来了新的语法糖 jsx ,使用 jsx 来模拟 vdom
如下:
<div class = "box">
<ul>
<li> {{ data.name }} </li>
</ul>
</div>
使用 jsx 模拟 vdom
1、获取数据
var data = {
id: 1,
name: '李四'
}
2、创建dom
<div class = "box">
<ul>
<li> {{ data.name }} </li>
</ul>
</div>
3、通过render函数解析jsx,将其转换成vdom结构
var vdom = {
tag: 'div',
attr: {
className: 'box'
},
content: [
{
tag: 'ul',
content: [
{
tag: 'li',
content: data.name
}
]
}
]
}
4、将vdom渲染成真是dom
使用render函数
5、数据更改
data.name = '张三'
vdom = {
tag: 'div',
attr: {
className: 'box'
},
content: [
{
tag: 'ul',
content: [
{
tag: 'li',
content: data.name //这里的data.name修改了
}
]
}
]
6、使用diff算法对比两次vdom,生成patch补丁对象
diff 算法是比较两个文件的差异,并将两个文件不同之处,生成一个补丁对象(patch)
7、根据 key
将 patch
对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的( 虚拟dom的惰性原则 )
3、什么是diff算法
diff
算法来源后端,用来比对两个文件的不同,前端将其应用于虚拟dom,vue中将 虚拟dom的diff算法放在了 patch.js
文件中,使用 js 来进行两个对象的比较( vdom 对象模型),diff算法是同级比较,会给每一个层级打一个标记,这个标记是一个数字( 这个数字就是 key
)
diff算法运行结束后返回的是 patch补丁对象