其一,为了让 Web 编程模型保持简单,浏览器的 JavaScript 引擎与 DOM 引擎共享一个主线程。任何 DOM API 调用都要先将 JS 数据结构转为 DOM 数据结构,再挂起 JS 引擎并启动 DOM 引擎,执行过后再把可能的返回值反转数据结构,重启 JS 引擎继续执行。这种上下文切换很耗性能,类似的还有单机进程间调用、远程过程调用等。
其二,很多 DOM API 的读写都涉及页面布局的“重新计算”,以确保返回值的准确,涉及样式、结构的还会触发页面“重新绘制”,更耗性能。综上,单次 DOM API 调用性能就不够好,频繁调用就会迅速积累上述损耗,导致 DOM 引擎占用主线程过久,用户操作不能及时触发 JS 事件回调,让用户感觉卡顿。所以,解决此问题的方案本质不在于用不用 jQuery、用不用虚拟 DOM,而是 —— 减少不必要的 DOM API 调用。虚拟 DOM 只是一种可选的方案,不是每种 Web 前端框架都用它。而减少不必要调用的各种方案,都遵循“在 JS 中缓存必要数据,计算界面更新时的阶段数据差异,只提交最终差集”的基本思路。虚拟 DOM 计算的是最终 DOM 结构的差异,还有的引擎计算的是 DOM 所绑定数据的差异,各有千秋。虚拟 DOM 的设计也不是性能首位的,React 意在保持较好性能的同时,拿它作为一个抽象层,方便向没有 DOM 接口的原生应用平台移植。
网友评论