1.1 声明式和命令式
(1)视图层框架通常分为命令式和声明式。
- 命令式:关注过程(例如jQuery)
const div = document.querySelector('#app') //获取id为app的div标签
div.innerText = 'hello world' // 设置文本
div.addEventListener('click',() => { alert('ok') })//绑定点击事件
- 声明式:关注结果
<div @click="() => alert('ok')">
hello world
</div>
(2)Vue.js帮我们封装了过程,内部是命令式的,暴露给用户的是声明式。
1.2 性能与可维护性的权衡
(1)结论:命令式代码性能优于声明式代码。
(2)例如上述代码,命令式代码若要修改text内容,直接修改即可,而声明式它需要找出前后差异并更新,那么有:
- 命令式代码的更新性能消耗=A,声明式代码的更新性能消耗=A+B (A是直接修改的性能消耗,B是找出差异的性能消耗)
(3)声明式代码的可维护性更强。
1.3 虚拟DOM的性能
(1)虚拟DOM是为了性能消耗最小化找出差异,对比JS操作和DOM运算,JS要快的多。
const html = <div><span>...</span></div> //构造HTML字符串
div.innerHTML = html //赋值给dom元素的innerHTML属性
(2)性能分析
对于创建页面:
-
innerHTML它的性能:HTML字符串拼接的计算量 + innerHTML的DOM计算量。
-
而虚拟DOM创建页面是先创建JS对象(理解为真实DOM的描述),再递归遍历虚拟DOM树并创建真实的DOM,它的性能:创建JS对象的计算量 + 创建真实的DOM的计算量。
对于更新页面:
-
innerHTML,它是重构HTML字符串再重新设置DOM元素的innerHTML属性 <=> 销毁旧的DOM元素,再创建新的DOM元素。
-
对于虚拟DOM更新页面,它是重建JS对象,再比较新旧虚拟DOM找出不同并更新它。
二者在宏观的角度上,若是在同个数量级上,创建页面时,性能二者差异不大,但在更新页面时,虚拟DOM在JS层面的运算只是多个diff运算,不过产生数量级的差异,而DOM层面运算,虚拟DOM只会更新必要的元素,但innerHTML需要全部更新,若页面很大,此时的虚拟DOM的优势体现出来了。
1.4 运行时和编译时
(1)纯运行时:设计Render函数,用户为该函数提供一个树形的数据对象,然后Render函数将该对象递归渲染成DOM元素。
const obj = { // 规定的树形结构的数据对象
tag: 'div', // 代表标签名称
children: [ // 代表子节点
{tag: 'span', children: 'hello world' }
]
}
function Render(obj, root) {
const el = document.creatElement(obj.tag)
if(typeof obj.children === 'string') {
const text = document.creatTextNode(obj.children)
el.appendChild(text)
} else if (obj.children) {
//数组,递归调用Render,使用el作为root参数
obj.children.forEach((child) => Render(child, el))
}
root.appendChild(el) // 将元素添加到root
}
Render(obj,document.body) //渲染到body中
(2)运行时+编译时:用户提供HTML字符串,Comlier函数将其编译成数据对象在给Render函数运行时处理。
<div>
<span> hello world </span>
</div>
const html =
<div>
<span> hello world </span>
</div>
const obj = Complier(html) // 调用Complier编译得到树形结构的数据对象
Render(obj,document.body) // 调用Render进行渲染
(3)编译时:将HTML字符串编译成命令式代码。
const div = document.creatElement('div')
const span = document.creatElement('span')
span.innerText = 'hello world'
div.appendChild(span)
document.body.appendChild(div)
- Vue.js 3 保持了运行时+编译时的架构,在保持灵活性的基础上能够尽可能的去优化。