我正在尝试制定一种有效的算法来更改一堆节点上的许多类,但我发现我对 javascript 如何遍历 DOM 的理解存在很大的漏洞。
浏览器/javascript 是否像 flash 一样使用弹性跑道?或者是更多的事件驱动,每次有变化时整个显示都会重新绘制?
“弹性跑道”是一种闪光范例,您可以在其中想象一个巨大的大环,闪光环绕着它。在用户处理时间期间,更改会累积,而在 Flash 处理时间期间,Flash 引擎会反复运行并应用所有更改。
另一种方法是事件模型,每次属性更改时都会重新绘制整个屏幕 - 这可能是浏览器所做的,但我不确定。
我可以想到混合算法,如果没有变化,什么也不会发生——但如果有变化,它们就可以累积起来——有点像我水槽上的盘子。
有没有人能快速描述用于处理属性更改和 DOM 插入的算法。
最佳答案
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
│ │ │
│ │ │
└────◀─────┴─────────────────◀─────────────────┘
正如他们所说,剩下的就是历史了。当 Microsoft 复制 javascript 时,他们必须复制事件循环以保持与 Netscape 的兼容。因此,从那时起,每个人都必须做同样的事情才能保持与 Netscape 和 IE 的兼容。
请注意,javascript 没有任何手动递归到事件循环的功能(某些语言,例如 tcl,可以做到这一点)因此浏览器必须等到没有更多的 javascript 可以执行才重绘页面。在脚本结束之前不能强制重绘页面。
正是出于这个原因,当您尝试在创建后立即读取元素的宽度或高度等计算值时,有时会返回错误的值 - 浏览器尚未绘制它们。如果您真的需要在页面重绘后执行代码,解决方法是使用超时值为 0 的 setTimeout
以允许浏览器运行一轮事件循环。
其他详细信息:
似乎有一种异常情况会触发昂贵的回流。请注意,重排是浏览器计算页面布局。它通常在浏览器需要绘制更改后的页面时触发。
当页面中的某些内容发生变化时,回流计算会排队 - 不会立即执行。正如上面的描述,回流只会在 javascript 执行结束时执行。但是有一种情况会导致浏览器立即执行回流计算:如果您尝试读取任何计算值,例如宽度和高度。
有关更多信息,请参阅此相关问题:When does reflow happen in a DOM environment?
关于javascript - javascript是否使用弹性赛道算法进行处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19616477/