第一篇 框架设计概览
本篇主要对于框架设计思路的取舍进行讲解
权衡的艺术
命令式和声明式
首先来介绍一下命令式和声明式的区别和优缺点
- 原生js
const div = document.querySelector('#app')
div.innerHTML = 'hello world'
div.addEventListener('click', () => { alert('ok') })
- 命令式(以jQuery为例)
$('#app') // 获取div
.text('hello world') // 设置文本
.on('click', () => { 'ok' }) // 绑定事件
- 声明式(Vue.js)
<div @click="()=>alert('ok')" > hello world</div>
从上面的代码可以感觉到,命令式的代码与原生js相似,代码描述的是“做事的过程”;而声明式框架则更关注结果。实际上,Vue.js帮我们封装了过程,内部还是命令式,暴露给用户的则更加声明式。
二者的权衡
先抛出一个结果,在代码性能层面:命令式优于声明式(该结论的前提是,命令式代码编写的足够优雅)
因为在运行代码时,命令式明确知道要修改什么;而声明式为了实现最优更新,需要在内部找到前后代码的差异,再进行修改
- 命令式代码的更新性能消耗 = 修改消耗
- 声明式代码的更新性能消耗 = 寻找差异的消耗 + 修改消耗
既然性能方面命令式由于声明式,那声明式有什么优点呢?
声明式避免了手动操作DOM的问题,更加易于入门(比较难写出性能较差的代码)以及后期的维护
Vue.js,或者说开发声明式框架的设计者目标则是:在保持可维护性的同时让性能损失最小化。
虚拟DOM
在上面的内容中我们说了声明式框架在内部进行了差异寻找,Vue为了实现寻找差异时对性能的最小化消耗,使用了虚拟DOM
在本节我们可以简单的将虚拟DOM理解为使用一个方法将html文件中的节点都转化为了JS(树)格式的数据(我们将该过程的实现用VNode表示),这颗树就是虚拟DOM
下面我们对JS层面的计算和DOM层面的计算进行性能比较
如上图,上边的代码是纯JS层面的计算,循环了10000次;下面是DOM操作循环10000,可以看出JS比DOM操作快几个量级
得出这个结论后,我们来看一下使用innerHTML
创建页面和使用虚拟DOM
创建页面的性能区别
- 使用
innerHTML
创建页面性能:HTML 字符串拼接的计算量 + innerHTML 的 DOM计算量 - 使用虚拟DOM创建页面性能:创建 JavaScript 对象的计算量 (html转js)+ 创建真实 DOM 的计算量
经过比较可以发现:在创建页面时,虚拟DOM和innerHTML
的性能消耗差距不大,都是一次JS层面的运算+一次DOM层面的运算
接下来我们比较一下二者在更新页面时的性能
innerHTML
采用的是,一次js运算+摧毁旧的DOM+创建新DOM- 虚拟DOM采用,将新页面VNode+Diff算法比较+个别DOM更新
二者相比:innerHTML
的DOM操作相比于虚拟DOM多的多,这时虚拟DOM的优势就体现出来了
所以得出一个结论
Vue的便选择了一个较为折中的办法