jQueryイベントの処理について学習し始めたばかりの頃、ブラウザがデフォルトの動作を実行するのを阻止する方法について、clickイベントのコードを以下に示します.
$("a.toggle").click(function () {
$("#mydiv").toggle();
return false; // Prevent browser from visiting `#`
});
この関数はtoggleを使用してmydivを表示または非表示にし、ブラウザがhrefで指定したリンクにアクセスし続けることを阻止します.
上記の例では、ブラウザがデフォルトの動作を実行することを阻止するために「return false」を使用する悪い習慣を身につけることができます.この記事では、ブラウザがデフォルトの動作を実行することを阻止する2つの非常に重要なトピックについて説明します.
•正しい方法を選択:return falseまたはpreventDefault、stopPropagationまたはstopImmediatePropagation•適切な場所を選択し、開始、終了、または中間の場所:イベントコールバックのどの部分でブラウザのデフォルト動作をキャンセルしますか?注意:この記事でevent bubbling(イベントバブル)といえば、ほとんどのイベントが最初のDOMでトリガーされ、その後DOMツリーを介して上に移動し、各レベルの親要素でトリガーされ、兄弟ノードやサブノードでイベントがバブルされないことを表現したいと思います(イベントが下にバブルされた場合、イベントキャプチャ(event capturing)と呼びます).ここでは、イベントのバブルとスナップについて詳しく説明することができます.
正しい方法を選ぶ
「return false」がこんなに誤用されているのは、私たちが渡した仕事を終えたように見えるためで、ブラウザは私たちをhrefのリンクにリダイレクトすることはなく、フォームも提出されませんが、これはいったい何が間違っていますか?
「return false」はいったい何をしたのか.
「return false」を呼び出すたびに、実際には3つのことをしました.
•event.preventDefault();•event.stopPropagation();•コールバック関数の実行を停止し、すぐに戻ります.「待って」と叫んだ!ブラウザにデフォルトの動作を停止させたいだけです.他の2つのことをする必要はありません.
この3つのうち、ブラウザがデフォルトの動作を継続することを阻止するために使用されるのはpreventDefaultだけです.イベントのバブルを停止しない限り、return falseを使用すると、コードに大きなリスクが埋め込まれます.このような誤用がどのような結果をもたらすかを実際の例で見てみましょう.
これは私たちがプレゼンテーションするために使用するHTMLです.
次に、ユーザーが記事タイトルをクリックしたときにdiv.contentdに記事を動的にロードしたいとします.
jQuery(document).ready(function ($) {
$("div.post h2 a").click(function () {
var a = $(this),
href = a.attr('href'), // Let jQuery normalize `href`,
content = a.parent().next();
content.load(href + " #content");
return false; // "cancel" the default behavior of following the link
});
});
このコードは正常に動作します(少なくとも現在は)が、この考えに沿って続行すると、ユーザーがdiv.post要素(またはそのサブ要素)をクリックしたときにactiveクラスを追加したい場合は、div.postに1つ追加する必要があります.
clickコールバック:
// Inside Document Ready:
var posts = $("div.post");
posts.click(function () {
// Remove active from all div.post
posts.removeClass("active");
// Add it back to this one
$(this).addClass("active");
});
今、投稿のタイトルをクリックすると、このコードは動作しますか?答えはできません.タイトルのclickコールバックでreturn falseを使用しているので、私たちが使用すべきではありません.「return false」はevent.preventDefault()に等しく、event.stopPropagation()を追加しているので、イベントバブルは終了し、clickイベントはdiv.postにバブルされません.私たちが追加したイベントコールバックはもちろん呼び出されません.
ライブやdelegateイベントと混ぜて使うと、状況はさらに悪化します.
$("a").click(function () {
// do something
return false;
});
$("a").live("click", function () {
// THIS WON'T FIRE
});
では、私たちが本当に必要なものは何ですか?
preventDefault()
ほとんどの場合、return falseを使用する場合、実際に必要なのはe.preventDefault()です.e.preventDefaultを使用するには、eventパラメータを消去関数に渡したことを確認する必要があります(この例では、e):
$("a").click(function (e) {
// e == our event data
e.preventDefault();
});
すべての作業を完了しますが、親ノードがイベントを処理し続けることを阻止することはありません.コードに置く制限が少ないほど、コードが柔軟になり、メンテナンスが容易になることを覚えておいてください.
stopPropagation()
しかし、イベントのバブルを止める必要がある場合があります.次の例を見てみましょう.
Normal text and then a
link and then more text.
次に、div上のaリンク以外の場所をクリックした場合、背景を変えるなど、何かが起こりたいと仮定しますが、ユーザーがaリンクをクリックする行為に影響を与えることはできません(可用性の観点から、この例はあまりよくありません.ユーザーが他の場所をクリックしたときに何かが起こることを望んでいないかもしれません).
$("div.post").click(function () {
// Do the first thing;
});
$("div.post a").click(function (e) {
// Don't cancel the browser's default action
// and don't bubble this event!
e.stopPropagation();
});
この場合、return falseを使用するとdivのclickイベントはトリガーされませんが、ユーザーはポイントのリンクに到達しません.
stopImmediatePropagation()
この方法では、現在のオブジェクトに他の処理関数がバインドされている場合でも、1つのオブジェクトにバインドされているすべてのイベントがバインド順に実行されるイベントが停止します.次の例を参照してください.
$("div a").click(function () {
// Do something
});
$("div a").click(function (e) {
// Do something else
e.stopImmediatePropagation();
});
$("div a").click(function () {
// THIS NEVER FIRES
});
$("div").click(function () {
// THIS NEVER FIRES
});
この例は違和感を感じるかもしれませんが、そうではありませんが、コードが非常に複雑であれば、異なるwidgetsとpluginが同じオブジェクトにイベントを追加する可能性があります.このような場合、stopImmediatePropagationを理解し、使用する必要があります.
return false
preventDefaultとstopPropagationを同時に必要とし、コールバック実行が完了するまでブラウザのデフォルトの動作を停止するコードを受け入れることができます.では、「return false」を使用することができます.しかし、他のjQuery開発者に書かれたプレゼンテーションコードでこの方法を使用しないことを強くお勧めします.これは、より多くの誤用をもたらすため、使用しなければならないと確信している場合にのみ「return false」を使用することができます.
適切な場所を選択
「return false」を使用すると、コールバック関数の実行が終了してからブラウザのデフォルト動作をキャンセルするだけですが、e.preventDefaultを使用すると、関数のどの部分に配置してもブラウザのデフォルト動作をいつでも停止することができます.
1.開発段階では、常に最初の行に置くべきです.あなたが最もしたくないことは、formをajaxに変更してコミットすることをデバッグしている間に、古い方法でコミットされている可能性があります.
2.製品フェーズで、プログレッシブ・エンハンスメント(progressive enhancement)を使用している場合は、コールバックの終了位置、または論理的終点に配置します.通常のページでプログレッシブ・エンハンスメントを使用している場合は、ブラウザがJSをサポートしていない場合(または無効になっている場合)、リンクされたclickイベントとフォームのコミット・イベントの処理をサーバ側で考慮する必要があります.ここでの利点は、JSを閉じることを考慮せず、jsをサポートするときの強狂だけを考慮することです.もしあなたのコールバックコードのエラーが異常を投げ出したら、次のコードを見てみましょう.
var data = {};
$("a").click(function (e) {
e.preventDefault(); // cancel default behavior
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// The original link doesn't work AND the "cool"
// JavaScript has broken. The user is left with NOTHING!
});
では、同じイベントを見て、preventDefault呼び出しを下に置く効果を見てみましょう.
>
var data = {};
$("a").click(function (e) {
// Throws an error because `my` is undefined
$("body").append(data.my.link);
// This line is never reached, and your website
// falls back to using the `href` instead of this
// "cool" broken JavaScript!
e.preventDefault(); // cancel default behavior
});
これはフォームの提出にも有効で、エラーにもっとよく対応することができます.コードが正常に動作していることを期待しないでください.エラーが発生したときに正しい対応があるのは、コードがエラーしないと仮定するよりも優れています.
3.制品の段阶で、もし机能のこの设计JSならば、それではまた第1行に置くべきです.
関数の最初の行である必要はありませんが、早ければ早いほど良いことを覚えておいてください.ここでの原則は、関数の機能がJSによって実現されている場合(サービス側のインタラクションにかかわらない)、互換性を考慮する必要はありません.この場合、最初の行に追加するとURLに#文字が表示されるのを防ぐことができますが、明らかに、できるだけ多くのエラー処理コードを追加する必要があります.エラー時にユーザーが戸惑うのを防止します.
結論
この文章が伝える情報は、ブラウザがデフォルトの動作を実行するのを阻止する必要があるときに正しい選択をするのに十分であることを望んでいます.覚えておいてください.あなたが本当に何をしているかを知っているときだけ、「return false」を使用して、関数の正しい位置で対応するコードを呼び出していることを確認します.最後に、できるだけコードの柔軟性を維持して、できるだけ「return false」を使わないでください.