jQuery focus()和blur()事件的滞后问题

时间:2009-10-28 21:37:26

标签: jquery javascript-events click mouseevent conflict

我正在尝试创建一个使用一些jQuery的导航菜单。我希望键盘用户能够获得与鼠标用户相同的体验,因此我在我的hover()focus()事件处理程序中复制了blur()事件处理程序中的功能。出于某种原因,当用户点击链接时,这会导致Firefox和IE显着滞后,而在focus()blur()代码被取出时不会发生这种情况。我怎样才能加快速度呢?我已经做了尽可能多的优化,因为我的有限的javascript知识将允许,但我没有看到任何“加速”,所以我认为它可能与这些浏览器如何处理事件有关。

我有什么重要的东西可以忽略吗?或者有没有其他方法可以在不使用这些事件的情况下保留键盘用户的可访问性?

        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);
            }
        );  
    });

您可以查看here

2 个答案:

答案 0 :(得分:3)

您的代码中有许多不必要的lengthening of the scope chain,更长的范围链需要更长时间才能解决。它可以缩短为以下

$("navbar a").click(blah) 
             .hover(foo,bar)
             .focus(foo)
             .blur(bar);

希望这会导致较少的明显延迟。如果您在进行此更改后仍然看到明显滞后,请发布事件处理函数的代码,因为可能会对该代码进行改进。

修改

在回复你的评论时,你可以使用传入的event对象的target属性获取函数中的索引,该属性将是引发事件的元素。因此,要获取<a>中id为导航栏的所有<a>元素中的<ul>元素的索引,我们可以使用每个{{{ 1}}包含在<a>中,因此每种情况下的索引都是相同的。请注意,<li>将是引发点击事件的event.target元素,<a>将是event.target.parentNode的父元素,即<a> }

要获取索引,您可以使用

<li>

这将消除包装hoverState的匿名函数事件处理程序的需要。

这是一些重做的代码

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;
} 

答案 1 :(得分:0)

我完全意外地解决了这个问题。我意识到我的问题并不是真正的滞后,这只是“事件冲突”的症状。

据我所知,问题是focus()是通过跳转到链接或可以获得焦点的元素上的mousedown()来触发的。因此,每次点击链接时,它都会得到关注。但是,在释放鼠标之前,click()事件尚未完成。因此,我在Firefox和IE中看到的效果是mousedown()mouseup()之间略有延迟的结果。我尝试将代码中的.click()事件处理换成mousedown(),因为它只是我注意的一个事件,所以我决定将它集成到我的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函数绑定到mousedown()事件。我不确定为什么会这样,但确实如此。它也修复了IE中的问题。扼杀,它在Chrome中引发了一个新问题,它太小了,我甚至都不用担心。

如果没有Russ的帮助,我不认为我能够解决这个问题,所以我想再次感谢他对他的所有帮助。