虚拟dom && diff算法 ( 王者 )
- 虚拟dom是什么?
- 先看下面的小实验
/*
需求: 有一个变量 count 的初始值时 0,经过一系列运算,得到10001,然后将结果写入box中
*/
var box = document.querySelector( '.box' )
// 我们可能会这么写
var count = 0 ;
console.time( 'a' )
for( var i = 0 ; i < 10001 ; i++ ){
count ++
box.innerHTML = count
}
console.timeEnd( 'a' ) // a字符输出花费的时间
// 我们肯定会这么写
count = 0
console.time( 'b' )
for( var i = 0 ; i < 10001 ; i++ ){
count ++
}
box.innerHTML = count
console.timeEnd( 'b' )
// 对比以上 a b 输出花费的时间
- 从上面的小实验中我们可以得出一个结论
更少的DOM操作会减少性能损耗,运行速度更快,所以我们应该先操作数据再去操作dom - 由以上结论慢慢的在前端引入了一个概念在框架中叫虚拟dom
- vdom是什么?
- 他是一个object对象模型,用来模拟真实dom节点的结构
需求:vdom如何模拟真实的dom,如果将来我想在ul中增加一个li,li的内容为“我是谁”,在增加十个li,内容为:xxx看下边<div class = "box"> <ul> <li> 我是帅哥 </li> </ul> </div> var list = document.querySelector( '.list' ) var li = document.createElement( 'LI' ) li.innerHTML = ' 我是谁 ' list.appendChild( li )
- 虚拟dom的使用基本流程
- 1.获取数据( ajax fetch )
var data = {
id: 1,
name: '1121'
}
-
- 创建vdom
var vdom = {
tag: 'div',
attr: {
className: 'box'
},
content: [
{
tag: 'ul',
content: [
{
tag: 'li',
content: data.name
}
]
}
]
}
-
- 初次渲染 vdom( vdom渲染成真实dom )
// var div = document.createElement('DIV')
// div.className = 'box'
// var ul = document.createElement('UL')
// var li = document.createElement('LI')
- vue中使用的是一个叫做jsx语法+render函数
- jsx语法:我们的网页结构一般都是很复杂的,这时我们使用 vdom去模拟dom结构,发现vdom这个对象模型太大了,也长了, 所以我们想,如果能在js中也能够书写dom标签结构那就好了, 所以结合了javascript + xml 搞出了一个新的语法糖jsx , 用jsx来模拟vdom
<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
}
]
}
]
}
- 将vdom渲染成真实dom(render函数)
- 更改数据,data.name=“亮哥”
data.name = '亮哥'
vdom = {
tag: 'div',
attr: {
className: 'box'
},
content: [
{
tag: 'ul',
content: [
{
tag: 'li',
content: data.name
}
]
}
]
}
-
- 使用diff算法比对两次vdom,生成patch对象
-
- 根据key将patch对象渲染到页面中改变的结构上,而其他没有改变的地方是不做任何修改的( 虚拟dom的惰性原则 )
- diff算法是什么?
- diff算法是比较两个文件的差异,并将两个文件不同之处,将这个不同之处生成一个补丁对象(patch)
diff算法来源后端,前端将其应用于虚拟dom的diff算法
vue中将 虚拟dom的diff算法放在了patch.js文件中,使用js来进行两个对象的比较( vdom 对象模型 )diff算法是同级比较
给每一个层级打一个标记,这个标记是一个数字( 这个数字就是 key ) - 这个key是啥
- id为app的dom结构其实是一个模板,其实就是jsx
- 案例:以一个案例来说明key是用来做标识的
<div id="app">
<ul>
<li v-for = " (item,index) in list" :key = "item.id">
<p> {{ item.text }} </p>
<div>
<button @click = "changeStyle"> 修改样式 </button>
<button @click = "remove( index )">删除 </button>
</div>
</li>
</ul>
</div>
new Vue({
el: '#app',
data: {
list: [
{
id: 1,
text: '敲代码1'
},
{
id: 2,
text: '敲代码2'
}
]
},
methods: {
changeStyle ( e ) {
//接下我写的是为了给大家看key的作用,但是这段代码将来不要出现,
// 理由: 我们应该避免操作真实dom
e.target.parentNode.parentNode.style.background = 'red'
},
remove ( index ) {
this.list.splice( index, 1 )
}
}
})
- diff算法运行结束之后,返回什么?
- patch对象
注意: vue是一是MVVM框架,Vue高性能的原因之一就是vdom
ackground = ‘red’
},
remove ( index ) {
this.list.splice( index, 1 )
}
}
})
4. diff算法运行结束之后,返回什么?
- patch对象
注意: vue是一是MVVM框架,Vue高性能的原因之一就是vdom
深化: Vue vdom vs React vdom 有何不一样?(敬请期待)