0%

虚拟DOM

命令式框架与声明式框架:

命令式框架:关注过程(Jquery)

1
2
3
$('#app')
.text('hello world')
.on('click',()=>alert('ok'))

声明式框架:关注结果(Vue.js)

1
<div @click='()=>alert('ok')'></div>

结论:声明式代码的性能不优于命令式代码的性能

声明式代码的更新性能消耗=找出差异的性能消耗+直接修改的性能消耗

Vue3中虚拟DOM的性能:

创建JavaScript对象的计算量+创建真实DOM的计算量

比较:

纯JavaScript:Js运算+DOM运算(性能因素)

虚拟DOM:创建Js对象(Vnode)+Diff+必要的DOM更新(与数据量变化有关)

innerHTML:渲染HTML字符串+销毁所有旧DOM,新建所有新DOM(与模板大小有关)

结论:

性能

innerHTML<虚拟DOM<原始JavaScript

心智负担

虚拟DOM<innerHTML<原生JavaScript

可维护性

虚拟DOM>innerHTML和原生JS

框架的设计可以有三种选择:

  • 纯运行时
  • 运行时+编译时(Vue3)
  • 纯编译时

1.纯运行时

一个树型结构的数据对象

1
2
3
4
5
6
const obj={
tag:'div',
children:[
{tag:'span',children:'hello world'}
]
}

tag:标签名,children:子节点

render:

1
2
3
4
5
6
7
8
9
10
function Render(obj,root){
const el = document.createElement(obj.tag)
if(typeof children ==='string'){
const text=document.createTextNode(obj,children)
el.appendChild(text)
}else if(obj.children){
obj.children.forEach((child)=>Render(child,el))
}
root.appendChild(el)
}
1
Render(obj,document.body)

2.运行时+编译时

编写一个Compiler函数,把HTML标签编译成树型结构的对象

1
2
3
4
5
const html=`<div>
<span>Hello world</span>
</div>`
const obj=Compiler(html)
Render(obj,document.body)

3.纯编译式:(Svelte)

1
2
3
4
5
6
7
8
<div><span>hello world</span></div>
//就是
const div=document.createElement('div')
const span=document.createElement('span')
const text=document.createElement('hello wrold')
span.appendChild(text)
div.appendChild(span)
document.body.appendChild(div)