杭州网站建设多少钱,北京做视觉网站,厦门广告公司有哪些,宁波网站排名优化公司参考文章做的总结#xff0c;如有不足之处请指正#xff01; 在讲虚拟dom之前#xff0c;先讲讲#xff0c;为什么前端操作dom会导致页面性能降低#xff1f; 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎#xff1f;
JavaScript引擎是一个专门处理JavaScript脚… 参考文章做的总结如有不足之处请指正 在讲虚拟dom之前先讲讲为什么前端操作dom会导致页面性能降低 先说几个概念 有助于后面的理解 什么是 JavaScript 引擎
JavaScript引擎是一个专门处理JavaScript脚本的虚拟机
能够将 Javascript 代码处理并执行的运行环境什么是渲染引擎
渲染引擎的职责就是渲染即在浏览器窗口中显示所请求的内容。这是每一个浏览器的核心部分所以渲染引擎也称为浏览器内核。它负责取得网页的内容(HTML、XML、图象等等)、整理信息(例如加入CSS等)以及计算网页的显示方式然后会输出至显示器浏览器的渲染机制
1、从下载文档到渲染页面的过程中浏览器会通过解析HTML文档来构建DOM树解析CSS产生CSS规则树CSSOM。
2、渲染过程中如果遇到script就停止渲染执行JS代码。因为浏览器有GUI渲染线程与JS引擎线程为了防止渲染出现不可预期的结果这两个线程是互斥的关系。 JavaScript的加载、解析与执行会阻塞DOM的构建。
3、之后根据DOM树和CSS规则树构建渲染树Render-Tree在这个过程中CSS会根据选择器匹配HTML元素。渲染树包括了每个元素的大小、边距等样式属性渲染树中不包含设置为 display: none; 的隐藏元素及head、script等不可见元素但是对于visibility: hidden;或opacity: 0;的元素它们会占据屏幕空间因此它们将出现在渲染树中。 最后浏览器根据元素的坐标和大小来计算每个元素的位置并绘制这些元素到页面上。JavaScript中 js 引擎和渲染引擎浏览器内核是独立实现的。使用 js 去操作 DOM 时本质上是 JS 引擎和渲染引擎之间进行了“跨界交流”。每操作一次 DOM都要跨界一次。跨界的次数一多就会产生比较明显的性能问题。 在浏览器中DOM的实现和ECMAScript的实现是分离的。比如在Chrome中使用WebKit中的WebCore处理DOM和渲染但ECMAScript是在V8引擎中实现的。所以通过JavaScript代码调用DOM接口相当于两个独立模块的交互。相比较在同一模块中的调用这种跨模块的调用其性能损耗是很高的。 DOM操作通常会导致浏览器的重绘repaint和回流reflow也叫重布局重绘和回流的代价很高。** 重绘指的是页面的某些部分要重新绘制比如颜色或背景色的修改元素的位置和尺寸并未改变。
回流则是元素的位置或尺寸发生了改变浏览器需要重新计算渲染树导致渲染树的一部分或全部发生变化渲染树重新建立后浏览器再重新绘制页面上受影响的元素。
回流的代价比重绘的代价高很多重绘不一定是因为回流但回流一定会导致重绘。
浏览器渲染页面流程 参考 JS操作DOM为什么会影响性能
正是因为这样 才会引入虚拟dom
虚拟DOM的意义就在于使找出差异的性能消耗最小化直接操作DOM的性能开销是庞大的
但是即便是使用虚拟DOM最终还是要改变真实DOM也就是说必要的DOM操作是不可避免的,
而虚拟DOM则通过它的diff算法使得DOM的更新范围尽可能变小降低了真实DOM操作的性能开销
同时通过框架的封装给开发者提供了一种更友好的声明式的前端开发方式下面举个例子 操作真实dom和虚拟dom的区别比如 有A、B、C、D四个人。
先让A站第一个在让B站第二个C站第三个但是我最后让D站第一个然后其他就往后移
(直接操作真实的DOM节点的话浏览器会一个一个从头到尾执行一边)这样其他三个人之前的排位置的时间算是白花了还要往旁边挪开空出一个位置给D。
四个人还好但是要是四百个人呢399个人需要移动位置真的是有点浪费时间和精力了。
所以那有没有更好的办法呢
这个时候虚拟DOM就显得更加优秀了。虚拟DOM是一个js对象。怎么理解这个js对象呢
我们都知道对象使用之前要定义不定义直接使用的话就会报错。也就是说是用不了。
而这个虚拟DOM呢就像是一个空对象操作虚拟DOM就像是网这个对象里面添加属性和对应的属性值。
对象内的属性全部定义好了之后再按照这个对象里面的内容全部转化输送给真实的DOM让其在页面中渲染出来。因为这个对象不可能一直保持不变在开发中出现代码的增删改是很正常的现象。
操作的是虚拟DOM那是所以只要对象一改动就能马上反应到虚拟DOM上。那又是如何反应的呢
这里面又牵扯到一个概念就是diff算法。
反应的方式就是通过diff算法来实现的。对象更新时会生成一个新DOM对象diff算法就是把新的DOM对象和老的DOM对象进行比较1、发现新属性里没有老属性那么老属性就直接卸载新属性直接安装
2、发现新属性的和老属性全部相同属性值也有可能是对象也要往下面核对那么就保留
3、发现同一个属性里新和老的有些值不同那么则要排列比较看哪些修改了哪些是新增的哪些是删除的。
这样在一定程度上也比更深的遍历发现同更加节约时间。因为老对象的改变则会使真实的DOM也会发生改变这样就在页面上实现了刷新在上面3的内容中我们又可以得到一个知识点那就是虚拟DOM的key值。
(Vue2 的模板语法即被写在 template 标签内的所有 HTML 标签并非直接展示在页面上而是会先被 Vue 进行解析生成虚拟DOM节点之后再由虚拟DOM转为真实DOM真实DOM才会真正显示在页面上。在虚拟DOM转换的过程中如何提升解析效率便是通过 key。key值就相当于给这些属性值加上了一个标签这样我们就可以通过这个key值去找到对应的值与之比较或是别的操作。所以这里我们就要求key值最好是独一无二的。如果用index作为key值得话如果值得位置有变动那么对应的index指向的就是变动后的值所以变动后的值的位置和原来的位置是不是一样不能确定因此index作为key值会有可能会存在一定偏差。看一下页面渲染的流程解析HTML - 生成DOM - 生成 CSSOM - Layout - Paint - Compiler 下面对比一下修改DOM时真实DOM操作和Virtual DOM的过程来看一下它们重排重绘的性能消耗 真实DOM∶ 生成HTML字符串重建所有的DOM元素 虚拟DOM∶ 生成vNode DOMDiff必要的dom更新 !--这是普通的Html标签写法-
a classlink hrefhttps://github.com/facebook/reactReacta//这是在js中手动生成相同dom的写法
var a document.createElement(a)
a.setAttribute(class, link)
a.setAttribute(href, https://github.com/facebook/react)
a.appendChild(document.createTextNode(React))
//这是一种封装沿用的React.createElement的命名
var a React.createElement(a, {className: link,href: https://github.com/facebook/react
}, React)
React.createElement 的方法名看似创建了一个Element实质只是一个轻量级的数据结构其最简形式如下
var a {type: a,props: {children: React,className: link,href: facebook/react · GitHub},_isReactElement: true
}React.render(a, document.body)React.render(ReactElement, DOM) 中所谓的 ReactElement是指私有属性_isReactElement 为 true 的一种数据结构而非真正的Element。 所有html结构都可以用js dom来构造而且能将构造的步骤封装起来做到「数据-dom结构」的映射。缓存初始数据新数据进来时与旧数据对比找到差异根据差异本身的性质进行dom操作无差异则不作为。dom本身在js中就是一种数据结构console.dir(document.body)在控制台可以看到body的数据结构。然而dom相关的数据丰富而且复杂我们其实只关心少数元素的少数属性。建立一个javascript plain object非常轻量用它保存我们真正关心的与dom相关的少数数据对它进行操作然后对比操作前后的差异再根据映射关系去操作真正的dom无疑能提高性能。这就是虚拟DOM的理念。 加入虚拟dom之后的浏览器更新
1、将页面改变的内容应用到虚拟 DOM 上而不是直接应用到 DOM 上 2、变化被应用到虚拟 DOM 上时虚拟 DOM 并不急着去渲染页面而仅仅是调整虚拟 DOM 的内部状态这样操作虚拟 DOM 的代价就变得非常轻了。 3、在虚拟 DOM 收集到足够的改变时再把这些变化一次性应用到真实的 DOM 上。 这里参考vue中如何将虚拟dom转为真实dom 超级推荐看这个 小白也能懂的 vue是如何渲染虚拟dom到dom上的 虚拟dom的缺点 1、首次渲染大量 DOM 时由于多了一层虚拟 DOM 的计算会比 innerHTML 插入慢。代码更多体积更大 2、内存占用增大 3、 小量的单一的dom修改使用虚拟dom成本反而更高不如直接修改真实dom快 这篇文章是翻阅资料后得到的总结