浏览器渲染和JavaScript执行是否同时发生?

时间:2011-12-06 22:22:03

标签: javascript jquery asynchronous rendering web

例如,如果我有这个:

$('#button').click(function() {
    $.get('/question', function(data) {
        $('#question').html(data);
        $('#question').dialog( ... );
    });
    return false;
});

在显示对话框之前,用户会在短时间内看到问题内容吗?

注意:通常情况下,我只是手动隐藏#question,但实际上在html()dialog()之间插入了另一个jQuery插件,其内容不得被'隐藏'。

4 个答案:

答案 0 :(得分:1)

简答

是的,在显示对话框之前,用户可能会在短时间内看到问题内容。

修复

为了确保您在显示对话框之前不会立即看到#question的内容,请在显示之前将#question置于屏幕外。之后,调用需要#question的jQuery插件。最后,隐藏#question并恢复其位置。

<强> CSS

#question
{
    display: none;
}

<强>的JavaScript

$('#button').click(function() {
  $.get('/question', function(data) {
    var question = $('#question');
    question.html(data);
    var position = question.css('position');
    var top = question.css('top');
    var left = question.css('left');
    question.css({ position: 'absolute', top: -1000, left: -1000 }).show();
    //whatever you need to do with #question while it's not hidden
    question.hide().css({ position: position, top: top, left: left });
    question.dialog( ... );
  });
  return false;
});

答案 1 :(得分:0)

这是初始化任何与DOM相关的活动应该在$(document).ready()内完成/触发的原因。

因此,如果你把$ .get语句放在doc ready中,你可以确保HTML中的所有元素都已经呈现,并且可以通过JS与之交互。

$(document).ready(function () {
  $.get('/question', function(data) {
    $('#question').html(data);
    $('#question').dialog( ... );
  });
});

答案 2 :(得分:0)

浏览器将向上呈现DOM直到该调用,此时它将停止并解析/执行您的js。这就是为什么将所有脚本标记放在页面底部被认为是最佳实践的原因(这样浏览器就可以渲染足够的DOM,这样访问者就不会盯着空白的白色屏幕)。

使用

$(document).ready();

可以在一定程度上缓解这种情况,但如果您真的担心它何时添加到DOM,请确保您的代码添加到HTML的body标记的最底部。

参考文献:

http://developer.yahoo.com/blogs/ydn/posts/2007/07/high_performanc_5/

答案 3 :(得分:0)

在你的情况下绝对不是,因为你正在使用框架。它的工作原理如下:

1)随着页面逐步加载,从外部文件请求脚本代码。在解析脚本请求之前,HTML解析器必须解析脚本标记。这段代码在被调用时执行,但它在JavaScript解释器可用的时候被提供给JavaScript解释器。

2)直接驻留在页面中的脚本代码被送入解释器,因为HTML解析器会解析HTML代码并遇到脚本标记。函数内部代码在调用时执行,但有一个例外。否则代码会在解释后立即执行。一个例外是当一个功能块紧跟“()”后,表示立即调用。

3)最初执行的大多数代码都是从使用“onload”事件进行的函数调用中执行的。当静态DOM从HTML解析器完全可用以及请求来自初始静态HTML的所有资产请求时,就会发生onload事件。在使用旧浏览器的某些边缘情况下,可能会发生冲突条件,在页面中创建竞争条件,以防止onload事件被触发或在非常延迟之后。

4)您正在使用jQuery,因此在可用性方面处于严重劣势。 jQuery代码是JavaScript代码,因此它必须像任何其他JavaScript一样输入JavaScript解释器。在任何jQuery代码执行之前,必须遵守本文中的所有先前要点。

5)当我执行A / B测试时,我需要尽可能早地尽可能快地执行代码,以尽量减少页面上的闪烁,因此框架绝对不是一个选项。在这种情况下,我按照以下步骤操作:

5a)我在我需要访问的DOM节点之后直接找到第一个id属性。 5b)我编写了一个函数来测试该节点的可用性。如果节点可用,那么它上面的区域是可用的,所以我知道我是坚实的。请考虑以下示例:

    var test = function () {
        var a = document.getElementById("first_node_lower_than_I_need");
        if (a !== null && typeof a === "object") {
            //my code here, because I know my target area is available
        } else {
            setTimeout(test, 100);
        }
    };
    setTimeout(test, 100);

5c)请注意,在上面的示例代码中,我使用setTimout延迟调用我的函数,为DOM提供了一个战斗机会。如果函数提前执行就没问题,因为我正在递归地调用它,延迟给DOM一些额外的加载时间。如果将延迟设置为50ms或更低,则会增加IE8中的执行时间,因为对该功能进行了大量不必要的调用。我建议将延迟保持在100毫秒,以便在浏览器中实现理想的平衡,但是如果你真的想在新浏览器中快速执行,那么将第一个延迟设置为50毫秒,这是函数外部的延迟,并保持另一个延迟为100毫秒。

5d)使用上述方法尽量减少对innerHTML属性的使用,或者非常熟悉目标页面以了解何时可以使用innerHTML。 innerHTML的问题在于它更改页面输出而不将这些更改报告回内存中已解析的DOM,这通常是无关的断开连接。但是,在这种情况下,它肯定是相关的,因为您注入的代码可以多快和早地执行。这是一个问题,因为稍后执行的其他代码(例如onload事件或jQuery的ready事件)将覆盖您的更改,或者无法找到他们受尊重的DOM加载,只是将它们的执行完全放在一起。如果您的目标是DOM树中的一个非常高级别的节点,这尤其是一个重要的问题,因此在选择使用innerHTML的节点或仅使用DOM方法时,为了您的安全性是非常具体的。这有点复杂,因为您无法使用仅限DOM方法的解决方案,因为您无法使用nodeValue方法跨浏览器更改文本节点,因为IE7不支持此方法。

如果您需要在完成DOM解析之前执行JavaScript代码,请不要使用JavaScript框架。使用简单的常规JavaScript代码编写并优化它的地狱。否则你将总是闪烁,静态HTML下载越大,闪烁就会越长越明显。此外,jQuery代码的执行速度往往比常规优化的JavaScript慢得多,因为它依赖于像选择器这样的CSS。如果您需要注入的jQuery代码在非常大的静态HTML文档上执行大型任务,那么在没有超时的情况下,不可能在IE7中完成执行。