jQuery focus()およびblur()イベントの遅れの問題
-
08-07-2019 - |
質問
jQueryを使用するナビゲーションメニューを作成しようとしています。キーボードユーザーにマウスユーザーと同じエクスペリエンスを提供したかったため、hover()
およびfocus()
イベントハンドラーでblur()
イベントハンドラーにある機能を複製しています。何らかの理由で、これにより、ユーザーがリンクをクリックしたときにFirefoxおよびIEで顕著な遅延が発生します。これは、<=>および<=>コードが取り出されたときに発生しません。これを高速化するにはどうすればよいですか?私は私の限られたJavaScriptの知識が許す限りの最適化を行いましたが、<!> quot; speedup <!> quot;を見たことがないので、これらのブラウザがイベントを処理する方法に関連していると考えています。
見落としている主要なものはありますか?または、これらのイベントを使用しないでキーボードユーザーのアクセシビリティを維持する代替方法はありますか?
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
私はこれを完全な事故で解決しました。私の問題は実際には遅延ではなく、<!> quot;イベントの競合<!> quot;の症状にすぎないことに気付きました。
私が知る限り、問題は、focus()
がリンクへのタブ移動またはフォーカスを受け取ることができる要素のmousedown()
によってトリガーされることです。そのため、リンクがクリックされるたびに、フォーカスが置かれます。ただし、マウスを放すまでclick()
イベントは完了しません。したがって、FirefoxとIEで見た効果は、mouseup()
と.click()
の間のわずかな遅延の結果でした。コード内の<=>イベント処理を<=>に交換しようとしましたが、ただ1つのイベントなので注意していたので、それを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で新たな問題を引き起こします。あまりにも軽微なので、心配することすらありません。
ラスの助けがなければこの問題を解決できなかったと思うので、これに関する彼の助けすべてに再び感謝したいと思います。
他のヒント
不必要なの延長コード内のスコープチェーンを使用します。スコープチェーンが長いと、解決に時間がかかります。次のように短縮できます
$("navbar a").click(blah)
.hover(foo,bar)
.focus(foo)
.blur(bar);
うまくいけば、これにより目立った遅れが少なくなるはずです。この変更を行った後も顕著なラグが見られる場合は、イベントハンドラー関数のコードを投稿してください。そのコードにも改善が加えられる可能性があるためです。
編集:
コメントへの応答で、渡されたevent
オブジェクトのtarget
プロパティを使用して関数のインデックスを取得できます。これは、イベントが発生した要素になります。そのため、ID navbar を持つ<a>
のすべての<ul>
要素の<li>
要素のインデックスを取得するには、各event.target
が< =>、したがって、それぞれの場合のインデックスは同じになります。これを念頭に置いて、event.target.parentNode
はクリックイベントが発生する<=>要素、<=>は<=>
インデックスを取得するには、使用できます
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);