javascript 是否使用弹性赛道算法进行处理

IT技术 javascript performance algorithm dom
2021-02-10 18:01:13

我正在尝试制定一种有效的算法来更改一堆节点上的许多类,但我发现我对 javascript 如何遍历 DOM 的理解有一个很大的漏洞。

浏览器/javascript 是否像 Flash 一样使用弹性赛道?还是更多的事件驱动,每次发生变化时都会重新绘制整个显示?

“弹性赛道”是一种闪存范式,您可以在其中想象一个巨大的大循环,它会在周围闪烁。在用户处理时间变化积累期间,在闪存处理时间期间,闪存引擎竞争并应用所有更改——一遍又一遍。

另一种选择是事件模型,每次属性更改时都会重绘整个屏幕 - 这可能是浏览器所做的,但我不确定。

我可以想到混合算法,如果没有变化,什么都不会发生——但如果有变化,它们就可以累积——有点像我水槽上的盘子。

有没有人对用于处理属性更改和 DOM 插入的算法进行快速描述。

1个回答

Flash 的“弹性赛道”是从浏览器继承而来的。当然,在浏览器领域我们不这么称呼它——我们称它为事件循环。

javascript 事件循环的历史始于 Netscape 上的渐进式 GIF 和 JPEG 渲染。渐进式渲染——绘制部分加载的内容——需要 Netscape 实现异步下载-渲染引擎。当 Brendan Eich 实现 javascript 时,这个异步事件循环已经存在。因此,向其添加另一层是一项相当简单的任务。

因此,浏览器的事件循环类似于以下内容:

    Event loop
        ┌──────────┐
        │          │
        │          │
        │          ▼
        │        check if there's any new ───────▶ parse data
        │        data on the network                    │
        │          │                                    │
        │          ▼                                    │
        │        check if we need to execute  ◀─────────┘
        │        any javascript ──────────────────▶ execute
        │          │                               javascript
        │          ▼                                  │
        │        check if we need to ◀────────────────┘
        │        redraw the page  ──────────────▶ redraw page
        │          │                                   │
        │          │                                   │
        └────◀─────┴─────────────────◀─────────────────┘

其余的,正如他们所说,是历史。当微软复制 javascript 时,他们不得不复制事件循环以保持与 Netscape 的兼容。因此,从那时起,每个人都必须这样做才能与 Netscape 和 IE 保持兼容。

请注意,javascript 没有任何手动递归到事件循环的功能(某些语言,例如 tcl,可以这样做),因此浏览器必须等到没有更多 javascript 可以执行,然后才能重绘页面。页面重绘不能强制发生,直到脚本结束。

正是由于这个原因,当您尝试在创建后立即读取它们时,计算值(例如元素的宽度或高度)有时会返回错误的值 - 浏览器尚未绘制它们。如果您确实需要在页面重绘后执行代码,则解决方法是setTimeout使用超时值为 0 的 a 以允许浏览器运行一轮事件循环。


附加细节:

似乎有一种特殊情况会触发昂贵的回流。请注意,回流是浏览器计算页面布局。如果浏览器需要绘制更改的页面,通常会触发它。

当页面中的某些内容发生更改时,回流计算会排队 - 不会立即执行。与上面的描述一样,回流只会在 javascript 执行结束时执行。但是有一种情况会导致浏览器立即执行回流计算:如果您尝试读取任何计算值,例如宽度和高度。

有关更多信息,请参阅此相关问题:在 DOM 环境中何时发生回流?

嗯.. 似乎还有一种情况会触发回流(回流是浏览器计算对象布局而不必绘制到屏幕上,尽管它们往往一起发生)。根据我的 google-fu,当您尝试访问元素的计算位置时会触发回流。因此,当您调用该getBoundingRect方法时,它们会重新计算请参阅:stackoverflow.com/questions/510213/...
2021-03-15 18:01:13
你是手工还是用软件制作了格式化的ascii文本?
2021-03-31 18:01:13
这很好 - 这意味着我可以在 DOM 中遍历一个列表并添加和删除一堆样式类,而无需重绘每个类 - 只需要检查显示的更精细的细节:我在其他地方读过的任何一个都可能有回流问题
2021-04-04 18:01:13
@克里斯:手动。这是我对 SO 的较长答案的典型代表。虽然有时它会因为我是第二个(或第三个)答案而惩罚我。
2021-04-08 18:01:13
这个小提琴表明重新计算在脚本块完成执行之前完成,因为打印的坐标肯定会改变。我想知道在这种情况下他们是否会重新计算相关的属性访问。
2021-04-12 18:01:13