如何消除渲染后的“闪烁”?

时间:2009-01-21 00:20:16

标签: javascript jquery html ajax dom

我已经尽力使用Javascript / Ajax技术成为纯粹主义者,确保所有Ajax-y行为都是基本功能的增强,而当Javascript被禁用时,该站点也完全正常运行。但是,这会导致一些问题。

在某些情况下,只有在浏览器中启用Javascript时,才能看到DOM节点。在其他情况下,它应该仅在禁用时可见。以表格上的提交按钮为例,该表单具有自动提交的onchange处理程序(使用JQuery的表单插件):

<form method="post" action=".">
    <label for="id_state">State:</label>
    <select name="state" id="id_state" onchange="$(this.form).ajaxSubmit(ajax_submit_handler);">
        <option value="AL">Alabama</option>
        <option value="AK">Alaska</option>
    </select>
    <input class="with_js_disabled" type="submit" value="OK" />
</form>

和Javascript:

<script type="text/javascript">
    $(document).ready(function()
    {
        $(".with_js_disabled").hide();
    });
</script>

启用Javascript时,不需要提交按钮(由于onchange处理程序)。但是,JQuery的$(document).ready函数(以及更直接的document.onload)仅在页面完全加载和呈现后调用 - 因此,最初显示提交按钮,当Javascript为时,会出现“flash”执行并且节点的显示设置为“无”。

我接受这是开展业务的成本,并没有找到解决方法。但是有一种我不知道的技术可以最大限度地减少效果,甚至可以直接消除它吗?

修改

下面很多人提到的<noscript>解决方案似乎很有希望,但在Safari上并不适合我。然而Prestaul的第二个建议很有效:

<body>
    <script type="text/javascript">
        document.body.className += ' has_js';
    </script>
    <!-- the rest of your page -->
</body>

然后可以使用直接CSS设置样式:

body .js_enabled_only { display: none; }
body .js_disabled_only { display: block; }
body.has_js .js_enabled_only { display: block; }
body.has_js .js_disabled_only { display: none; }

这第二行仅供参考,可以(并且应该)删除,以避免不应该显示元素的情况:阻止。同样,对于其他显示样式,您可能需要在第三行上使用不同的变体。但是这个解决方案很干净,IMO,在我的测试中完全消除了闪烁效应。

6 个答案:

答案 0 :(得分:10)

如何结合其中一些解决方案:

<style type="text/javascript">
    .only-without-script {
        display: none;
    }
</style>
<noscript>
    <style type="text/javascript">
        .only-with-script {
            display: none;
        }
        .only-without-script {
            display: block;
        }
    </style>
</noscript>

或者我更喜欢在正文中添加一个类(将<script>标记放在正文的顶部而不使用.ready事件):

<head>
    <style type="text/javascript">
        body.has-script .something-not-ajaxy {
            display: none;
        }

        input.ajaxy-submit {
            display: none;
        }
        body.has-script input.ajaxy-submit {
            display: inline;
        }
    </style>
</head>
<body>
    <script type="text/javascript">
        document.body.className += ' has-script';
    </script>
    <!-- the rest of your page -->
</body>

答案 1 :(得分:5)

对于与您的情况相同的情况,我通常会将提交按钮放在<noscript>标记周围。没有人建议它,所以我不确定这些部分是否被认为是不好的做法,但它是我使用的,它对我有用。

如果您只想在启用Javascript时显示节点,则可以在头部进行:

<noscript>
    <style type="text/css">
    .js-enabled { display: none; }
    </style>
</noscript>

然后为任何仅限Javascript的元素提供js-enabled类。

答案 2 :(得分:2)

就像David说的那样,你可以添加一个Javascript,添加一个样式表来隐藏所有“不必要的”html元素:

<head>
  ...
  <script type="text/javascript" language="javascript">
    document.write('<style type="text/css"> .disabled-if-javascript { display: none; } </style>');
  </script>
</head>
...

如果启用了Javascript,它会在加载正文之前将类“disabled-if-javascript”的所有元素设置为隐藏。如果启用了javascript,只需将此类添加到需要隐藏的所有元素中。您可能还需要一个启用了相反的类的enabled-if-javascript,以显示将为非javascript隐藏的某些元素。也许你需要在那里添加“!important”来覆盖现有的(非javascript)规则。

答案 3 :(得分:1)

我可以想到两种方法:

1 - 预先检测是否启用了Javascript并将该信息保存在cookie /会话中。这可以在首页完成,并且应该消除大多数闪烁。

2 - 使用livequery plugin,它会在元素添加到DOM时检测元素。您可以在Javascript完成加载时正确运行它,这应该在文档之前(它在头部)。

$('.with_js_disabled').livequery(function() {
     $(this).hide();
});

答案 4 :(得分:1)

只是一个想法:我不确定这是否可行,但您可以尝试在文档头中放置一些Javascript以编写一个隐藏按钮的CSS样式元素。

答案 5 :(得分:0)

一个简单的尝试:在关闭body标签之前添加<script>jQuery.ready();</script>

这会强制所有对'ready'事件的绑定都会被触发。如果你在文档的末尾激活它们,那么DOM就会被加载并准备就绪,即使尚未触发“本机”onDomContentLoaded事件。

当我想删除闪烁时,这通常对我有用,特别是在IE / win中,因为IE在jQuery的'ready'事件中拥有它自己的domready模拟器。