如何确保JS代码在DOM完全呈现之前不会运行?

时间:2013-11-26 21:33:33

标签: jquery

我有一个页面,其最终渲染由一些jQuery运行的JavaScript调整,格式为

<script>
(function ($) {
   //
})(jQuery);
</script>

这个JS根据DOM元素的初始大小和位置进行调整。

这在大多数情况下运作良好,但偶尔会有结果出来。

我认为原因是JavaScript试图获取尚未渲染的元素的位置,因此后续的定位计算出错了。

如何确保在此JS运行之前完全呈现DOM?

1 个答案:

答案 0 :(得分:3)

你说你已经等到jQuery的ready事件发生了。 (我想到我看到了你的回复评论说你是,但我现在没有看到该评论而引用的代码没有。)可以等到window load事件火灾,但这发生在这个过程的后期。

相反,我建议继续在ready(或更早,通过将脚本标记放在body的末尾而不使用ready)运行,但设置为计时器触发并重新检查您所依赖的事物的大小,如果这些更改则调整大小。初始计时器可能设置为“零”毫秒(实际上不是),然后可能再次设置为50,然后是100或200,然后只需调整window resize的大小。

像这样模糊的东西:

<!-- ...content... -->
<script src="yourscript.js"></script>
</body>
</html>

...其中yourscript.js是:

(function($) {
    var start = +new Date(),
        loaded = false,
        lastSizes = {}, // Sizes of relevant elements
        resizeTimer = 0;

    // Check resize on load, flagging that load is complete.
    // Maybe resize on resize.    
    $(window).load(function() {
        loaded = true;
        checkResize();
    }).resize(maybeResize);

    // Initial trigger    
    initialResizeCheck();

    // Actually do a resize operation
    function resize() {
        // ...your sizing logic, which sets the sizes in `lastSizes`
    }

    // Check the sizes in `lastSizes` vs. current ones, calls
    // `resize` if they're not set up yet or if they've changed.
    // (Wouldn't be uncommon for this to be combined with `resize`).
    function checkResize() {
    }

    // The function we use early on to proactively check until `load` fires    
    function initialResizeCheck() {
        var elapsed = +new Date() - start;

        checkResize();

        if (!loaded) {
            if (elapsed < 10) {
                setTimeout(initialResizeCheck, 0);
            }
            else if (elapsed < 100) {
                setTimeout(initialResizeCheck, 30);
            }
            else if (elapsed < 500) {
                setTimeout(initialResizeCheck, 100);
            }
        }
    }

    // Trigger a resize when the window is resized, but not until it
    // stops being resized.
    function maybeResize() {
        if (resizeTimer) {
            clearTimeout(resizeTimer);
        }
        resizeTimer = setTimeout(checkResize, 10);
    }

})(jQuery);

这些间隔完全是袖手旁观,但你明白了。积极主动,然后在必要时进行调整。