【发布时间】: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