我有一个非常大而复杂的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,等待一个完成,然后做另一个。仍然无济于事。有什么想法吗?
答案 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");
});
});
使用回调来延迟触发。看看这对你有用。