在循环内附加事件处理程序时浏览器性能有问题
Problematic browser performance when attaching event handler inside loop
我在创建插件时遇到问题。为变量 width
.
设置新值时出现问题
width
变量需要重新计算,如果用户调整他的浏览器。
如果我在循环内附加 resize
事件,它会使 性能出现问题 。
我想出了创建 closure
函数来包装所有代码的想法。所以,当用户调整他的浏览器大小时,我再次调用这个函数。
JS :
var self = this,
onScrollbarY = function() {
self.each(function() { // loop it
var el = $(this),
elLog = el.find(".scrollbarYLog"),
width = $(window).innerWidth(), // this value will change based on users browser width
onMouseOver = function() {
elLog.html(width);
};
elLog.on("mouseover", onMouseOver);
});
};
onScrollbarY(); // call it immediatly
$(window).on("resize", onScrollbarY); // if users resize its browser, call it again for getting new browser width
这是正确的实现方式吗?还是有比重新附加所有代码更有效的其他选项?
您首先遇到性能问题的原因是每次调用 .on('resize', ...)
时,您都注册了一个在该事件上运行的函数。所以在 5 个 resize
事件之后,你每次都会调用 5 个函数,这就是导致速度变慢的原因。
有两种方法可以解决这个问题:
- 只将一个处理程序附加到该事件(你最终做了什么);或
- 使用
.one('resize', ...)
事件处理程序注册一个函数,该函数只会在第一个下一个 resize
事件上触发。
用例 #1 是大多数开发人员使用和推荐的。您创建一个函数(如您的 onScrollbarY
)并使用 .on()
注册该函数,从您注册它的那一刻起,每次 resize
事件发生时都会调用该函数。
情况 #2 非常罕见,您可能不想使用 .one()
,除非您只想处理该事件的第一次出现,然后再处理 none。如果您想处理多个,则必须在事件发生后再次调用 .one()
以告诉它再次侦听该事件。
编辑: 您可以将代码简化为以下内容:
var $window = $(window),
width = $window.innerWidth(), // we know the initial width
$elLog = $(".scrollbarYLog"), // we find the scrollbar element
onResize = function() {
width = $window.innerWidth();
},
onMouseOver = function() {
$elLog.html(width);
};
// register the resize function with the "resize" event
$window.on("resize", onResize);
// register the mouseover function with the "mouseover" event on the scrollbar
$elLog.on("mouseover", onMouseOver);
// there is no need to call onResize(), as we've already set the width variable
我在创建插件时遇到问题。为变量 width
.
width
变量需要重新计算,如果用户调整他的浏览器。
如果我在循环内附加 resize
事件,它会使 性能出现问题 。
我想出了创建 closure
函数来包装所有代码的想法。所以,当用户调整他的浏览器大小时,我再次调用这个函数。
JS :
var self = this,
onScrollbarY = function() {
self.each(function() { // loop it
var el = $(this),
elLog = el.find(".scrollbarYLog"),
width = $(window).innerWidth(), // this value will change based on users browser width
onMouseOver = function() {
elLog.html(width);
};
elLog.on("mouseover", onMouseOver);
});
};
onScrollbarY(); // call it immediatly
$(window).on("resize", onScrollbarY); // if users resize its browser, call it again for getting new browser width
这是正确的实现方式吗?还是有比重新附加所有代码更有效的其他选项?
您首先遇到性能问题的原因是每次调用 .on('resize', ...)
时,您都注册了一个在该事件上运行的函数。所以在 5 个 resize
事件之后,你每次都会调用 5 个函数,这就是导致速度变慢的原因。
有两种方法可以解决这个问题:
- 只将一个处理程序附加到该事件(你最终做了什么);或
- 使用
.one('resize', ...)
事件处理程序注册一个函数,该函数只会在第一个下一个resize
事件上触发。
用例 #1 是大多数开发人员使用和推荐的。您创建一个函数(如您的 onScrollbarY
)并使用 .on()
注册该函数,从您注册它的那一刻起,每次 resize
事件发生时都会调用该函数。
情况 #2 非常罕见,您可能不想使用 .one()
,除非您只想处理该事件的第一次出现,然后再处理 none。如果您想处理多个,则必须在事件发生后再次调用 .one()
以告诉它再次侦听该事件。
编辑: 您可以将代码简化为以下内容:
var $window = $(window),
width = $window.innerWidth(), // we know the initial width
$elLog = $(".scrollbarYLog"), // we find the scrollbar element
onResize = function() {
width = $window.innerWidth();
},
onMouseOver = function() {
$elLog.html(width);
};
// register the resize function with the "resize" event
$window.on("resize", onResize);
// register the mouseover function with the "mouseover" event on the scrollbar
$elLog.on("mouseover", onMouseOver);
// there is no need to call onResize(), as we've already set the width variable