3

我正在尝试创建一个使用一些 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);
            }
        );  
    });

你可以在这里查看

4

2 回答 2

3

您的代码中有很多不必要的范围链延长,更长的范围链将需要更长的时间来解决。可以缩短为以下

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

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

编辑:

作为对您的评论的回应,您可以使用传入的event对象target属性获取函数中的索引,该属性将是引发事件的元素。因此,要获取具有 id navbar<a>中所有<a>元素的元素的索引,我们可以使用每个都包含在 a 中的事实,因此每种情况下的索引都是相同的。考虑到这一点,将是引发点击事件的元素,将是其父元素<ul><a><li>event.target<a>event.target.parentNode<a><li>

要获取索引,您可以使用

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);  
于 2009-10-28T22:52:22.183 回答
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 的帮助,我认为我无法解决这个问题,所以我想再次感谢他在这方面的所有帮助。

于 2009-11-06T17:54:52.497 回答