Javascript工作时延迟CSS渲染

时间:2015-07-30 21:38:52

标签: javascript jquery css click pseudo-element

我有一个非常大而复杂的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"的时间点可见渲染始终与产品网格重建和渲染同时进行。我还没有发布操作产品网格的代码,但是您可以知道行$theElement.trigger("filterOptionsChanged")触发了大量的数组和对象处理来构建新产品列表的文档片段,并更新了最后的DOM。我明白这可能需要一秒钟,这不是我的问题。但我不明白的是为什么我的"滴答盒"正在等待该事件的代码完成渲染之后。根据我的css,我需要的只是按钮上的一个类active,该代码在触发" filterOptionsChanged"上面的一行被触发。事件,所以它应该在任何产品网格发生变化之前触发。

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

我将首先尝试解决此问题。我读了很多关于"昂贵" 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呈现snappy。没有更多的问题。

我有一个模糊的想法,好吧,如果一个点击事件可以没有那个事件触发器,我需要一种方法来分离这两个。首先添加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,然后我添加我的类来显示勾选框,然后我解决了延迟。现在我说,当showLoading完成后,然后进行整个产品 - 网格操作。不要同时做这些,javascript,等待一个完成,然后做另一个。仍然无济于事。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

根据this,JavaScript中的所有函数调用都会阻止UI,直到完成为止;我打赌这包括原始函数调用以启动click事件。一个廉价的解决方案可能是用以下方法替换触发器:

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

有希望延迟触发器足够长时间以便浏览器重新绘制UI(您可以/应该在原始函数中添加一些加载图标,然后在超时中删除它)。您还可以查看web workers,它们看起来像是非常多的主题。

答案 1 :(得分:0)

试试这个,

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");
        });
    });

使用回调来延迟触发。看看这对你有用。