3

jQuery を使用するナビゲーション メニューを作成しようとしています。キーボード ユーザーがマウス ユーザーと同じエクスペリエンスを持てるようにしたかったので、イベント ハンドラーにある機能hover()を myfocus()および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 の問題も修正されます。Strangle、それは Chrome で新しい問題を引き起こします。それは非常にマイナーなので、心配する必要はありません。

ラスの助けがなければ、この問題を解決することはできなかったと思います。そのため、彼のすべての助けに改めて感謝したいと思います。

于 2009-11-06T17:54:52.497 に答える