【问题标题】:Does javascript process using an elastic racetrack algorithmjavascript 是否使用弹性赛道算法进行处理
【发布时间】:2013-11-06 03:27:21
【问题描述】:

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

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

“弹性跑道”是一种 flash 范例,您可以在其中想象一个 flash 循环的大循环。在用户处理期间,变化会逐渐增加,而在闪存处理期间,闪存引擎会四处运行并应用所有更改 - 一遍又一遍。

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

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

有没有人能简单介绍一下用于处理属性更改和 DOM 插入的算法。

【问题讨论】:

    标签: javascript performance algorithm 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 执行后再重绘页面。在脚本结束之前不能强制进行页面重绘。

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


    补充细节:

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

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

    有关更多信息,请参阅此相关问题:When does reflow happen in a DOM environment?

    【讨论】:

    • This fiddle 建议在脚本块完成执行之前完成重新计算,因为打印的坐标肯定会改变。我想知道在这种情况下他们是否会重新计算相关的属性访问。
    • Hmm.. 似乎还有一种情况会触发重排(重排是浏览器计算对象布局而不必绘制到屏幕上,尽管它们往往一起发生)。根据我的google-fu,当您尝试访问元素的计算位置时会触发重排。因此,当您调用 getBoundingRect 方法时,它们会重新计算。见:stackoverflow.com/questions/510213/…
    • 你是手动还是用软件制作了格式化的 ascii 文本?
    • @chris:手动。这是我对 SO 较长答案的典型代表。虽然有时它会因为我成为第二个(或第三个)答案而受到惩罚。
    • 这很好——这意味着我可以在 DOM 中遍历一个列表并添加和删除一堆样式类,而无需重绘每个样式类——只需要检查 display:none 上的更精细的细节我在别处读过可能有回流问题
    猜你喜欢
    • 1970-01-01
    • 2017-01-05
    • 2012-10-25
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多