延迟 CSS 渲染,而 Javascript 可以正常工作
Delayed CSS rendering while Javascript does it's work
我有一个非常大且复杂的 jQuery 插件,为简单起见,我将避免在此处发布。我的问题很简单,我就把它简化成相关代码:
我有一个点击事件附加到一组按钮:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
$theElement.trigger("filterOptionsChanged");
});
如果您转到此 link,您可以在左侧边栏中看到这些操作:
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" "tick-box" 需要一秒钟左右的时间。如果您看不到它,请尝试取消选中它,这对我来说需要更长的时间。 "tick" 可见渲染的时间点始终与产品网格重建和渲染同时进行。我没有发布操作产品网格的代码,但你可以知道行 $theElement.trigger("filterOptionsChanged")
触发大量数组和对象处理以构建新产品列表的文档片段,并更新 DOM 最后。我知道这可能需要一秒钟,这不是我的问题。但我不明白的是为什么我的 "tick-boxes" 一直等到该事件的代码完成呈现之后。根据我的 css,我需要的只是按钮上的 class active
,并且该代码在触发 "filterOptionsChanged" 事件的上方一行触发,因此它应该在触发之前触发任何产品网格都会发生变化。
现在。如果我在 chrome 中打开我的检查器,我实际上可以在产品网格更新之前看到活动的 classes 在单击时立即切换。但是,在我的 "filterOptionsChanged" 代码完成之前,添加刻度的 css 不会捕获元素上的活动 class。
我第一次尝试解决这个问题将在下面发布。我阅读了很多关于 "expensiveness" of 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
class,然后触发 "filterOptionsChanged"。我想,好的,jQuery 延期。这是代码:
$("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 是一个空白的延迟,然后我添加我的 classes 以显示复选框,然后我解决延迟。现在我说,当 showLoading 完成后,然后进行整个产品网格操作。不要同时做这些,javascript,等一个做完再做另一个。还是没有用。有什么想法吗?
根据 this,JavaScript 中的所有函数调用都会阻塞 UI 直到它们完成;我敢打赌,这包括启动点击事件的 original 函数调用。一个廉价的解决方案可能是用类似的东西替换触发器:
setTimeout(function() { $theElement.trigger("filterOptionsChanged"); }, 200);
这将有望延迟触发器足够长的时间,以便浏览器重新绘制 UI(您 could/should 在原始函数中添加一个小加载图标,然后在超时时将其删除)。您还可以查看 web workers,它们看起来几乎都是线程。
试试这个,
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");
});
});
使用回调延迟触发。看看这是否适合你。
我有一个非常大且复杂的 jQuery 插件,为简单起见,我将避免在此处发布。我的问题很简单,我就把它简化成相关代码:
我有一个点击事件附加到一组按钮:
$("ul.tick-boxes button").click(function(event) {
event.preventDefault();
$("ul.product-grid").addClass("loading");
$(this).toggleClass("active");
$theElement.trigger("filterOptionsChanged");
});
如果您转到此 link,您可以在左侧边栏中看到这些操作:
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" "tick-box" 需要一秒钟左右的时间。如果您看不到它,请尝试取消选中它,这对我来说需要更长的时间。 "tick" 可见渲染的时间点始终与产品网格重建和渲染同时进行。我没有发布操作产品网格的代码,但你可以知道行 $theElement.trigger("filterOptionsChanged")
触发大量数组和对象处理以构建新产品列表的文档片段,并更新 DOM 最后。我知道这可能需要一秒钟,这不是我的问题。但我不明白的是为什么我的 "tick-boxes" 一直等到该事件的代码完成呈现之后。根据我的 css,我需要的只是按钮上的 class active
,并且该代码在触发 "filterOptionsChanged" 事件的上方一行触发,因此它应该在触发之前触发任何产品网格都会发生变化。
现在。如果我在 chrome 中打开我的检查器,我实际上可以在产品网格更新之前看到活动的 classes 在单击时立即切换。但是,在我的 "filterOptionsChanged" 代码完成之前,添加刻度的 css 不会捕获元素上的活动 class。
我第一次尝试解决这个问题将在下面发布。我阅读了很多关于 "expensiveness" of 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
class,然后触发 "filterOptionsChanged"。我想,好的,jQuery 延期。这是代码:
$("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 是一个空白的延迟,然后我添加我的 classes 以显示复选框,然后我解决延迟。现在我说,当 showLoading 完成后,然后进行整个产品网格操作。不要同时做这些,javascript,等一个做完再做另一个。还是没有用。有什么想法吗?
根据 this,JavaScript 中的所有函数调用都会阻塞 UI 直到它们完成;我敢打赌,这包括启动点击事件的 original 函数调用。一个廉价的解决方案可能是用类似的东西替换触发器:
setTimeout(function() { $theElement.trigger("filterOptionsChanged"); }, 200);
这将有望延迟触发器足够长的时间,以便浏览器重新绘制 UI(您 could/should 在原始函数中添加一个小加载图标,然后在超时时将其删除)。您还可以查看 web workers,它们看起来几乎都是线程。
试试这个,
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");
});
});
使用回调延迟触发。看看这是否适合你。