在了解vue的源码之前我们要先知道什么是命令式编程,什么是声明式编程,像我们熟知的jQuery就为命令式的编程方式了,比如给一个div设置文本内容并给他添加一个点击事件,用jQuery的命令式编程就为:
$('#app').text('这是我的文本').on('click', () => alert('我被点击了'))
然而vue框架这种就属于声明式的编程方式,同样实现上面的功能则只需要:
<div @click="alert('我被点击了')" >这是我的文本</div>
我们不难看出,命令式编程主要看重的是过程,而声明式的编程主要看重的是结果,至于怎么实现这个‘结果’就不是我们要关心的了,我们只需要用声明式的方式告诉vue,我要这个文本,我要这个点击事件;
在这里我们先抛出一个结论:声明式代码的性能不优于命令式代码的性能
假如我们要把div的内容修改为hello word,如果是命令式编程的话就是:
div.textContent = 'hello word';
没有比上面这个方法性能更好的代码了,这就是极致性能的代码,但是声明式的代码就多了一步,对于vue的虚拟dom来说,多了一步中间的操作就是比较前后差异的地方,然后去更新变化的地方,也就是说: 命令式代码更新的性能消耗 = 声明式代码更新的性能小号 - 找出差异的性能消耗
但是没有疑问的来说,声明式代码对一个程序员来说是非常的方便敏捷开发与维护迭代的,为了综合这一个问题,我们现在的解决办法就是把找出差异的性能消耗尽可能去最小化,也就是采用虚拟dom;
但是采用虚拟dom的更新技术的性能理论上不可能比原生的javaScript操作dom更高,我们很难写出绝对优化的命令式代码,前文所说的原生javaScript实际上指的是document。createElement之类的DOM操作方法,并不包含innerHTML,我们早些年用jQuery或js编写页面的时候,使用innerHTML是非常常见的操作,那么问题就随之而来,innerHTML和vue的虚拟dom相比性能如何?也许你已经知道了虚拟dom的性能更好,但是有没有想过为什么。
对于innerHTML来说我们创建一个html页面需要构造一个类html的字符串,列入:
const html = `
<body>
<div>
</div>
</body>
`
你也为把这个字符串插上去就完事了,然而远远没有这么的简单,为了能渲染出页面,首先浏览器要把字符串解析长dom树,这是一个dom层的计算,dom层的计算远远要比javaScript要耗费性能的多得多;
况且我们正常去开发需要去拼接这个类html字符串,也就是 = HTML字符串拼接的计算 + innerHTML的dom计算量;
也就是说: 虚拟dom是创建新的javaScript对象 + diff算法去对比然后去更新必要的dom,而innerHTML是渲染HTML字符串后去销毁所有的旧dom然后再去创建所有的新的dom; 虚拟dom的性能主要取决于数据变化量,而innerHTML主要取决于模板大小;
虚拟dom的方式虽然没有原生javaScript性能好,但是它心智负担小,可维护强,性能属于中规中矩,从多个维度来思考的情况下,虚拟dom成了vue的最终解决方案;