jQuery focus()和blur()事件的滞后问题
-
08-07-2019 - |
题
我正在尝试创建一个使用一些jQuery的导航菜单。我希望键盘用户能够获得与鼠标用户相同的体验,因此我在我的hover()
和focus()
事件处理程序中复制了我的blur()
事件处理程序中的功能。出于某种原因,当用户点击链接时,这会导致Firefox和IE显着滞后,这在<=>和<=>代码被取出时不会发生。我怎样才能加快速度呢?我已经做了尽可能多的优化,因为我的有限的javascript知识将允许,但我还没有看到任何<!>“speedup <!>”,所以我认为它可能与这些浏览器如何处理事件有关
我有什么重要的东西可以忽略吗?或者有没有其他方法可以在不使用这些事件的情况下保留键盘用户的可访问性?
var statePad=0;
function stateChanger(ourStatePad) {
//the purpose of this function is to translate the current state of the menu into a different graphical representation of the menu state.
var tempVar=ouStatePad;
var tempArray = new Array;
tempArray[5]=0;
for (var x=0;x < 5;x++) {
tempArray[x]=tempVar % 10;
tempVar=(tempVar-tempArray[x])/10;
}
for (var arrayIndex=4;arrayIndex>=0;arrayIndex--) {
//Calculate the proper position in our CSS sprite, based on the each link's state, as well as it's neighbors'.
$(".block").eq(4 - arrayIndex)
.css(
"background-position",
//x-position
((4 - arrayIndex) * -100) + "px " +
//y-position
(tempArray[arrayIndex] + ((3 * tempArray[(arrayIndex) + 1]) * -30))) + "px";
}
}
function hoverState(index,sign) {
var placeholder=Math.pow(10,4-index);
if (statePad != placeholder*2)
statePad += (placeholder * sign);
stateChanger(statePad);
}
.click(function() {
var index=$("#navbar a").index(this);
statePad=Math.pow(10,(4-index))*2;
stateChanger(statePad);
$(".active").removeClass("active");
$(this).addClass("active");
})
.hover(
function () {
hoverState($("#navbar a").index(this),1);
},
function () {
hoverState($("#navbar a").index(this),-1);
});
$("#navbar a").focus(
function() {
hoverState($("#navbar a").index(this),1);
}
);
$("#navbar a").blur(
function() {
hoverState($("#navbar a").index(this),-1);
}
);
});
您可以查看此处
解决方案 2
我完全意外地解决了这个问题。我意识到我的问题实际上不是滞后,这只是<!>“事件冲突<!>”的症状。
据我所知,问题是focus()
是通过跳转到链接或mousedown()
触发可以获得焦点的元素来触发的。因此,每次点击链接时,它都会得到关注。但是,在释放鼠标之前,click()
事件不会完成。因此,我在Firefox和IE中看到的效果是mouseup()
和.click()
之间略有延迟的结果。我尝试将代码中的<=>事件处理换成<=>,因为它只是我注意的一个事件,所以我决定将它集成到我的hoverState()函数中。我最终得到了这个:
function hoverState(e) {
var index = $(e.target.parentNode).prevAll().length;
if (e.type == 'mousedown') {
statePad=Math.pow(10,(4-index))*2;
$(".active").removeClass('active');
$("#"+ e.target.id).addClass('active');
}
else {
var sign = (e.type === 'mouseenter' ||
e.type === 'focus')? 1 : -1;
var placeholder=Math.pow(10,4-index);
if (statePad != placeholder*2)
statePad += (placeholder * sign);
$('h1').text(statePad + " " + e.type);
}
stateChanger(statePad);
}
$("#navbar a").bind("mouseenter mouseleave focus blur mousedown", hoverState);
然而,这引起了一些奇怪的行为,搞砸了statePad变量。我回到了Russ Cam提供给我的代码,并开始重新思考问题。我在Opera中尝试过,我还没有完成,它运行良好。我在Safari和Chrome中试过它,它们像往常一样工作得很好。我在Firefox中尝试过它,只是试图找到使它与众不同的东西,并且...它正在工作!
我回顾了我的代码,结果发现我仍然将hoverState函数绑定到<=>事件。我不确定为什么会这样,但确实如此。它也修复了IE中的问题。扼杀,它在Chrome中引发了一个新问题,它太小了,我甚至都不用担心。
如果没有Russ的帮助,我不认为我能够解决这个问题,所以我想再次感谢他对他的所有帮助。
其他提示
有很多不必要的延长您的代码中的范围链以及更长的范围链将需要更长时间才能解决。它可以缩短为以下
$("navbar a").click(blah)
.hover(foo,bar)
.focus(foo)
.blur(bar);
希望这会导致较少的明显延迟。如果您在进行此更改后仍然看到明显滞后,请发布事件处理函数的代码,因为可能会对该代码进行改进。
修改强>
在回复您的注释时,您可以使用传入的event
对象的target
属性获取函数中的索引,该属性将是引发事件的元素。因此,要获取<a>
中包含id 导航栏的所有<ul>
元素中的<li>
元素的索引,我们可以使用每个event.target
包含在<< =>,因此每种情况下的索引都是相同的。考虑到这一点,event.target.parentNode
将是引发click事件的<=>元素,<=>将是<=>的父元素,即<=>
要获取索引,您可以使用
function hoverState(e) {
// get the index of the <a> element, which will be the same
// as the index of the <li> that contains it in the <ul>
//
var index = $(e.target.parentNode).prevAll().length;
//
// get the sign
var sign = (e.type === 'mouseenter' || e.type === 'focus')? 1 : -1;
}
这将消除包装hoverState的匿名函数事件处理程序的需要。
这是一些重做的代码
var statePad=0;
// the purpose of this function is to translate
// the current state of the menu into a different
// graphical representation of the menu state.
//
function stateChanger(ourStatePad) {
var tempVar=ourStatePad;
var tempArray = [0,0,0,0,0];
for (var x=0;x < 5;x++) {
tempArray[x]=tempVar % 10;
tempVar=(tempVar-tempArray[x])/10;
}
// Calculate the proper position in our CSS sprite,
// based on the each link's state, as well as it's neighbors'
//
var arrayIndex=4;
while (arrayIndex--) {
$("#rightpostheader div.block").eq(4 - arrayIndex)
.css(
"backgroundPosition",
//x-position
((4 - arrayIndex) * -100) + "px " +
//y-position
(tempArray[arrayIndex] + ((3 * tempArray[(arrayIndex) + 1]) * -30))) + "px";
}
}
function hoverState(e) {
var index = $(e.target.parentNode).prevAll().length;
var sign = (e.type === 'mouseenter' ||
e.type === 'focus')? 1 : -1;
var placeholder=Math.pow(10,4-index);
if (statePad != placeholder*2)
statePad += (placeholder * sign);
stateChanger(statePad);
}
$("#navbar a")
.click(function(e) {
// might be able to rework this into using hoverState too
var $this = $(e.target);
// get the index of the parent <li>
var index= $this.parent().prevAll().length;
statePad=Math.pow(10,(4-index))*2;
stateChanger(statePad);
$("#navbar a").removeClass('active');
$this.addClass('active');
})
.bind("mouseenter mouseleave focus blur", hoverState);