event.preventDefault()vs。return false(jQueryなし)


84

event.preventDefault()return falseは同じかと思いました。

私はいくつかのテストを行いました、そしてそれは

  • たとえば、イベントハンドラが古いモデルを使用して追加された場合

    elem.onclick = function(){
        return false;
    };
    

    次に、のreturn falseようなデフォルトのアクションを防ぎますevent.preventDefault()

  • たとえば、を使用してイベントハンドラが追加さaddEventListenerれた場合

    elem.addEventListener(
        'click',
        function(e){
            return false;
        },
        false
    );
    

    次に、return falseデフォルトのアクションを妨げません。

すべてのブラウザはこのように動作しますか?

との間にもっと違いはevent.preventDefault()ありreturn falseますか?

場合によっては、そのreturn falseようevent.preventDefault()に動作することに関するドキュメント(MDNでは見つかりませんでした)はどこにありますか?


私の質問はプレーンなJavaScriptに関するものであり、jQueryに関するものではないため、両方の質問のタイトルがほぼ同じであっても、event.preventDefault()の重複としてマークしないでください。


stackoverflow.com/questions/1357118/の複製…質問を読むと、jQuery固有の問題ではなく一般的なJSの問題であることがわかります。jQueryは、サンプルコードをできるだけ短く/クリーンにするためにのみ使用されました。
RaYell 2013年

13
@RaYellいいえ、jQueryのreturn false動作はプレーンJavaScriptの動作とは異なるためです。また、他の質問には、プレーンJSの違いを説明する答えがありません(それを説明するコメントしかありませんが、見つけるのは難しいです)。ですから、2つの異なる質問をする方が良いと思います。
oriol 2013年

回答:


55

W3Cドキュメントオブジェクトモデルイベント仕様1.3.1。イベント登録インターフェイスhandleEvent、EventListenerには戻り値がないと述べています。

handleEvent このメソッドは、EventListenerインターフェースが登録されたタイプのイベントが発生するたびに呼び出されます。[...]戻り値なし

1.2.4未満イベントのキャンセル文書には、次のようにも記載されています

キャンセルは、イベントのpreventDefaultメソッドを呼び出すことによって実行されます。イベントフローのいずれかのフェーズで1つ以上のEventListenersがpreventDefaultを呼び出すと、デフォルトのアクションがキャンセルされます。

これは、true / falseを返すことで、どのブラウザでも使用できるような効果を使用することを思いとどまらせるはずですevent.preventDefault()

更新

HTML5仕様では、実際には戻り値を異なる方法で処理する方法が指定されています。HTML仕様のセクション7.1.5.1には、次のように記載されています。

戻り値がWebIDLブール値のfalse値である場合は、イベントをキャンセルします。

「マウスオーバー」イベント以外のすべて。

結論

event.preventDefault()古い仕様、つまり古いブラウザと互換性があるので、ほとんどのプロジェクトで使用することをお勧めします。最先端のブラウザのみをサポートする必要がある場合にのみ、falseを返してキャンセルしても問題ありません。


2
このリンクは2000年に作成されました。HTML5仕様:w3.org/TR/html5/webappapis.html#event-handler-attributesは、多くのイベントの戻り値を処理するように見えます(マウスオーバーではありません): "戻り値がWebIDLブール値の場合偽の値、その後イベントをキャンセルする」
Charles L.

そして、chromeでのいくつかの簡単なテストから、両方ともfalseを返し、event.preventDefault()は伝播を停止しません。主に@Oriolの功績:伝播の停止通常の
Charles L.

このフィドルはの行動を比較しstopPropagation()preventDefault()、およびreturn falsejsfiddle.net/m1L6of9x。最近のブラウザでは、後者の2つは同じ動作をします。
Erik Koopmans

5

ここに、人々が問題をよりよく理解してトラブルシューティングするのに役立つかもしれないいくつかの例があります。

TL; DR

  • on*イベントハンドラー(onclickボタン要素の属性など):イベントをキャンセルするにはfalseを返します
  • addEventListenerは別のAPIであり、戻り値(例false)は無視されます:use event.preventDefault()
  • onclick="<somejs>"<somejs>onclick関数の本体にラップされているため、独自の潜在的な混乱があります。
  • ブラウザのdevtoolsAPIを使用してgetEventListeners、イベントハンドラが期待どおりに動作しない場合に、イベントリスナーがどのようにトラブルシューティングするかを確認します。

この例はclick<a>リンク付きのイベントに固有です...ただし、ほとんどのイベントタイプに一般化できます。

js-some-link-hookモーダルを開き、ページナビゲーションが発生しないようにするクラスのアンカー(リンク)があります。

以下の例は、MacOSMojaveのgooglechrome(71)で実行されました。

大きな落とし穴の1つonclick=functionNameは、それが使用するのと同じ動作であると想定することです。addEventListener

javascriptが有効になっているときにjavascriptで処理するアンカータグ(リンク)があるとしましょう。クリックされたときにブラウザがリンクをたどらないようにします(「デフォルトを防ぐ」動作)。

<a href="https://www.example.com/url/to/go/to/when/no/javascript"
   class="js-some-link-hook">click me!</a>

onclick属性

function eventHandler (event) {
    // want to prevent link navigation
    alert('eventHandler ran');
    return false;
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.setAttribute('onclick', eventHandler);
}
addEventListenerToElement();

次に、ブラウザのdevtoolsコンソールで実行します。

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output

...そしてあなたが見る:

function onclick(event) {
function eventHandler (event) {alert('eventHandler ran'); return false;}
}

これはまったく機能しません。onclick=ハンドラー関数を使用する場合、別の関数にラップされます。

関数参照を呼び出さずに指定したため、関数定義が含まれているが呼び出されていないことがわかります。つまり、要素がクリックされたときに実行されていることを確認する必要はありonclick="functionName()"ません。onclick="functionName"functionName

さらに、関数が呼び出されて関数がfalseを返した場合でも、関数はonclickそのfalse値を返さないことがわかります。これはイベントを「キャンセル」するために必要です。

これを修正するために、がからの戻り値(false)を返すonclickことreturn myHandlerFunc();を保証するように設定できonclickますmyHandlerFunc

return false;frommyHandlerFuncを削除して、onclicktoを変更することもできmyHandlerFunc(); return false;ますが、ハンドラー関数でロジックをまとめたい場合があるため、これはあまり意味がありません。

onclickjavascriptで設定onclickする場合、(私の例のように)javascriptではなくhtmlで直接設定する場合、onclick属性値は文字列型であり、すべてが機能することに注意してくださいonclickjavascriptを使用して設定する場合は、タイプに注意する必要があります。あなたが言うならelement.setAttribute('onclick', myHandlerFunc()) myHandlerFunc、今すぐ実行され、結果はクリックごとに実行されるのではなく、属性に保存されます。代わりに、属性値が文字列として設定されていることを確認する必要があります。 element.setAttribute('onclick', 'return myHandlerFunc();')

これがどのように機能するかを確認したので、コードを変更して必要な処理を実行できます。説明のための奇妙な例(このコードは使用しないでください):

function eventHandler (e) {
    // want to prevent link navigation
    alert('eventHandler ran');
    console.log(e);
    return false;
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.setAttribute('onclick', 'return ('+eventHandler+')(event);');
}
addEventListenerToElement();

eventHandler関数の定義を文字列にラップしたことがわかります。具体的には、先頭にreturnステートメントがある自己実行関数です。

再びchromedevtoolsコンソールで:

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output

...ショー:

function onclick(event) {
return (function eventHandler (e) {
        // want to prevent link navigation
        alert('eventHandler ran');
        console.log(e);
        return false;
    })(event);
}

...そうそう、それはうまくいくはずです。案の定、リンクをクリックするとアラートが表示され、アラートを閉じるとページがどこにも移動したり更新されたりしません。

onclick...に関するもう1つの注意事項eventイベント時にパラメータを受信して​​利用する場合は、「イベント」という名前であることに注意してください。名前を使用してハンドラー内でこれにアクセスできますevent(親onclick関数スコープから利用可能)。またはevent、パラメーターとして受け取るハンドラーを作成することもできます(テストに適しています)...たとえばonclick="return myEventHandler(event);"、前の例のように。

addEventListener

function eventHandler (ev) {
    // want to prevent link navigation
    alert('eventHandler ran');
    console.log(ev);
    return false;
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();

ブラウザdevtools:

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output

結果:

function eventHandler (ev) {
    // want to prevent link navigation
    alert('eventHandler ran');
    console.log(ev);
    return false;
}

だからあなたはすでに違いを見ることができます。ではaddEventListener、私たちは中に包まれていないonclick機能。ハンドラーはeventパラメーターを直接受け取ります(したがって、必要に応じて呼び出すことができます)。また、return falseここでは「トップレベル」にあり、のようにreturnステートメントを追加することを心配する必要はありませんonclick

したがって、動作するはずです。リンクをクリックすると、アラートが表示されます。アラートを閉じると、ページがナビゲート/更新されます。 つまり、falseを返すことによってイベントがキャンセルされなかった。

仕様を検索すると(下部のリソースを参照)、addEventListenerのコールバック/ハンドラー関数が戻り値の型をサポートしていないことがわかります。必要なものは何でも返すことができますが、ブラウザのAPI /インターフェースの一部ではないため、効果はありません。

解決策:...のevent.preventDefault()代わりに使用するreturn false;

function eventHandler (ev) {
    // want to prevent link navigation
    ev.preventDefault();
    alert('eventHandler ran');
}

function addEventListenerToElement () {
    var link = document.querySelector('.js-some-link-hook');
    link.addEventListener('click', eventHandler, false);
}
addEventListenerToElement();

ブラウザdevtools..。

var el = document.querySelector('a.js-some-link-hook'),
        listener = getEventListeners(el).click[0].listener;
console.log(''+listener); // to avoid truncation of output

与える...

function eventHandler (ev) {
    // want to prevent link navigation
    ev.preventDefault();
    alert('eventHandler ran');
}

...予想通り。

再テスト:

  • リンクをクリックします。
  • アラートを取得します。
  • アラートを閉じます。
  • ページのナビゲーションや更新は行われません...これが私たちが望んでいることです。

したがって、falseを返すaddEventListenerように使用event.preventDefault()しても、何も起こりません。

リソース

html5仕様(https://www.w3.org/TR/html5/webappapis.html#events)は、例と例の両方を使用してonclickおりaddEventListener、次のように言っているため、混乱を招きます。

イベントハンドラHおよびイベントオブジェクトEのイベントハンドラ処理アルゴリズムは次のとおりです。

..。

  1. 戻り値を次のように処理します。

..。

戻り値がWebIDLブール値のfalse値である場合は、イベントをキャンセルします。

その意味すると思わそれはそうreturn false両方のイベントをキャンセルaddEventListenerしてonclick

しかし、それらのリンクされた定義を見ると、次のようになりevent-handlerます。

イベントハンドラには名前があり、常に「on」で始まり、その後に対象のイベントの名前が続きます。

..。

イベントハンドラーは、2つの方法のいずれかで公開されます。

すべてのイベントハンドラーに共通する最初の方法は、イベントハンドラーのIDL属性としてです。

2番目の方法は、イベントハンドラーのコンテンツ属性としてです。HTML要素のイベントハンドラーとWindowオブジェクトの一部のイベントハンドラーは、この方法で公開されます。

https://www.w3.org/TR/html5/webappapis.html#event-handler

したがってreturn false、イベントのキャンセルは実際にはonclick(または一般的にon*)イベントハンドラーにのみ適用され、addEventListener異なるAPIを持つ経由で登録されたイベントハンドラーには適用されないようです。

addEventListenerAPIはhtml5仕様(on*イベントハンドラーのみ)でカバーされていないため、on*例のスタイルイベントハンドラーに固執していれば混乱は少なくなります。


-2

PreventDefault、stopPropogation、returnfalseの違い

違いを示す表

デフォルトのアクション–制御イベントが発生したときのサーバー側のアクション。

divコントロールがあり、その中にボタンがあるとします。したがって、divはボタンの親コントロールです。ボタンのクライアント側クリックイベントとサーバー側クリックイベントがあります。また、divのクライアント側クリックイベントもあります。

クライアント側のボタンのクリックイベントでは、次の3つの方法を使用して、親コントロールとサーバー側コードのアクションを制御できます。

  • return false-これにより、コントロールのクライアント側のイベントのみが許可されます。親コントロールのサーバー側イベントとクライアント側イベントは発生しません。

  • preventDefault()-これにより、クライアント側の制御イベントとその親制御が可能になります。サーバー側のイベント、すなわち。コントロールのデフォルトのアクションは実行されません。

  • stopPropogation()–これにより、コントロールのクライアント側とサーバー側のイベントが可能になります。コントロールのクライアント側イベントは許可されていません。


21
あなたは間違っていて、return false伝播を停止しないので、親コントロールが起動されます(デモ)。また、「サーバー側クリックイベント」とはどういう意味かわかりません。
オリオール

6
@初心者、この答えは無視してください。
ピラフ2015

4
サーバーサイドイベントについてのこのナンセンスは何ですか?-1
マークアメリー2016年

サーバー側のものは、サーバー上でイベントを処理できるASPについて考えていると思います。
アンドリュー

5
JavaScriptとイベントについて話すとき、「サーバー側」はありません。
rawpower 2016年

-12

return falseIE専用で、event.preventDefault()chrome、ff ...でサポートされています。最新のブラウザ


9
しかし、Firefoxでは、古いモデルを使用してイベントハンドラーが追加されたときのreturn falseように機能しますevent.preventDefault()
Oriol
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.