【问题标题】:Delayed CSS rendering while Javascript does it's workJavascript 工作时延迟 CSS 渲染
【发布时间】:2015-07-30 21:38:52
【问题描述】:

我有一个非常大且复杂的 jQuery 插件,为了简单起见,我将避免在此处发布。我的问题很简单,我只简化为相关代码:

我有一个附加到一组按钮的点击事件:

$("ul.tick-boxes button").click(function(event) {
    event.preventDefault();
    $("ul.product-grid").addClass("loading");
    $(this).toggleClass("active");
    $theElement.trigger("filterOptionsChanged");
});

如果您访问此链接,您可以在左侧边栏中看到这些操作:

http://mazer.com/collections/refrigerator?preview_theme_id=22019779

这是在您单击按钮时产生复选标记的 css:

ul.tick-boxes button.active .tick-box::after {
    content: "\e603";
    font-family: "custom-icons";
    color: #51425d;
    top: 2px;
    left: 2px;
    font-size: 0.75rem;
    position: absolute;
}

如果您的计算机和我的一样慢,那么当您单击这些过滤器选项时,“勾选”“复选框”需要一秒钟左右的时间。如果您看不到它,请尝试取消它,对我来说这需要更长的时间。 “tick”明显呈现的时间点始终与产品网格重建和呈现同时进行。我没有贴出操作product-grid的代码,但是你可以知道$theElement.trigger("filterOptionsChanged")这行触发了大量的数组和对象处理来构建新产品列表的文档片段,并在最后更新DOM .我知道这可能需要一秒钟,那不是我的问题。但是我不明白为什么我的“复选框”要等到该事件的代码完成渲染之后。根据我的 css,我只需要按钮上的一个类 active,并且该代码在触发“filterOptionsChanged”事件的上方一行被触发,因此它应该在任何产品网格更改发生之前触发。

现在。如果我在 chrome 中打开我的检查器,我实际上可以在产品网格更新之前看到活动类在单击时立即切换。但是,在我的“filterOptionsChanged”代码完成之前,添加刻度的 css 不会捕获元素上的活动类。

我第一次尝试解决这个问题将在下面发布。我读了很多关于 CSS 伪选择器的“昂贵”的文章。对于浏览器来说,这就像每次创建 ::after 元素时的 dom 操作。所以我然后写了这个css:

ul.tick-boxes button .tick-box::after {
    content: "\e603";
    font-family: "custom-icons";
    color: #51425d;
    top: 2px;
    left: 2px;
    font-size: 0.75rem;
    position: absolute;
    opacity: 0;
}

ul.tick-boxes button.active .tick-box::after {
    opacity: 1;
}

所以现在::after元素从一开始就一直存在,一开始就支付任何渲染成本,所以我的想法是,现在当我点击这个按钮时,勾号已经存在,我们只是给它一个不透明度为 1。没有解决延迟问题。

现在,我尝试完全删除“filterOptionsChanged”事件触发器。这使我的整个排序插件停止工作,但我现在不在乎,因为我想了解导致问题的原因。当我确实删除了该事件触发器时,按钮和 css 呈现活泼。没有更多的问题。

我有一个模糊的想法,好吧,如果单击事件可以在没有该事件触发器的情况下变得活泼,那么我需要一种将两者分开的方法。首先添加active 类,然后触发“filterOptionsChanged”。我认为,好的,jQuery Deferreds。这是代码:

$("ul.tick-boxes button").click(function(event) {
    event.preventDefault();
    var showLoading = jQuery.Deferred();
    $("ul.product-grid").addClass("loading");
    $(this).toggleClass("active");
    showLoading.resolve();
    $.when(showLoading).done(function() {
        $theElement.trigger("filterOptionsChanged");
    });
});

所以 showLoading 是一个空白的 Deferred,然后我添加我的类以显示复选框,然后我解决了 deferred。现在我说,当 showLoading 完成后,再进行整个产品网格操作。不要同时做这些,javascript,等待一个完成,然后做另一个。仍然无济于事。有什么想法吗?

【问题讨论】:

  • window.requestAnimationFrame 可能会有所帮助
  • 我不知道你的代码在做什么,但我没有看到任何 HTTP 请求进入。它没有理由这么慢,但没有看到它我无法提供有什么建议么。在现代计算机上构建一个页面的大片段的工作应该花费更少的时间(如果做得好的话)。然而,有很多昂贵的东西应该避免。
  • 很难说,因为它被缩小了,但我敢打赌,真正的问题就像那个“快速购物过滤器”一样。好像没那么快。
  • Pointy,基本上,bigFastShopifyFilter 正在执行以下操作:在页面加载时,插件一次向 shopify 服务器上的 json 端点发出 7 个 ajax 请求以检索所有产品.如果这些页面中的任何一个不为空,它会再进行 7 次调用,并重复直到找到一个空页面。然而,所有这些调用都发生在插件启动的开始,当你点击每个过滤器选项时,我的帖子是关于的,没有 ajax 调用,只有从 javascript 对象构建的文档片段。

标签: javascript jquery css click pseudo-element


【解决方案1】:

根据this,JavaScript 中的所有函数调用都会阻塞 UI,直到它们完成;我敢打赌,这包括启动点击事件的 original 函数调用。一个便宜的解决方案可能是将触发器替换为:

setTimeout(function() { $theElement.trigger("filterOptionsChanged"); }, 200);

这有望延迟触发器足够长的时间,以便浏览器重新绘制 UI(您可以/应该在原始函数中添加一个小加载图标,然后在超时时将其删除)。你也可以看看web workers,看起来它们几乎是线程。

【讨论】:

  • 亚历克斯,当场。这对我来说是革命性的,我不知道 js 在执行密集工作时会冻结 UI。我现在看到 Web Workers 是要走的路,但在 ie10 以下不支持它们,而且我正在开发一个在旧计算机上有很多用户的项目。尽管如此,您的快速修复使滴答声按钮变得活泼并启动了我想要的加载消息,而更密集的东西则可以正常工作。效果很好。也许我可以想出一个浏览器检查并将代码路由到 Web Worker 以便以后获得更好的解决方案。
  • 如果您进行浏览器检查,请确保检查功能,而不是版本typeof(Worker) === "undefined" 等等。干杯!
【解决方案2】:

试试这个,

CSS:

ul.tick-boxes button.active .tick-box::after {
    content: "\e603";
    font-family: "custom-icons";
    color: #51425d;
    top: 2px;
    left: 2px;
    font-size: 0.75rem;
    position: absolute;
}

JS:

    $("ul.tick-boxes button").click(function(event) {
        event.preventDefault();
        $("ul.product-grid").addClass("loading");
        $(this).toggleClass("active").fadeIn(10, function () {
            $theElement.trigger("filterOptionsChanged");
        });
    });

使用回调来延迟触发。看看这是否适合你。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 2011-03-12
    • 2016-01-10
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多