子アンカーがクリックされたときに親のonclickイベントが発生しないようにするにはどうすればよいですか?


346

私は現在、jQueryを使用してdivをクリック可能にしており、このdivにもアンカーがあります。私が遭遇している問題は、アンカーをクリックすると、両方のクリックイベントが発生することです(divとアンカー)。アンカーがクリックされたときにdivのonclickイベントが発生しないようにするにはどうすればよいですか?

壊れたコードは次のとおりです。

JavaScript

var url = $("#clickable a").attr("href");

$("#clickable").click(function() {
    window.location = url;
    return true;
})

HTML

<div id="clickable">
    <!-- Other content. -->
    <a href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

回答:


458

イベントは、クリックイベントが関連付けられているDOMの最も高いポイントにバブルします。したがって、この例では、divに明示的にクリック可能な要素が他にない場合でも、divのすべての子要素は、DIVのクリックイベントハンドラーがキャッチするまで、DOMまでクリックイベントをバブルします。

これに対する2つの解決策は、イベントを実際に誰が発生させたかを確認することです。jQueryは、イベントとともにeventargsオブジェクトを渡します。

$("#clickable").click(function(e) {
    var senderElement = e.target;
    // Check if sender is the <div> element e.g.
    // if($(e.target).is("div")) {
    window.location = url;
    return true;
});

リンクにクリックイベントハンドラーをアタッチして、独自のハンドラーの実行後にイベントバブリング停止するように指示することもできます。

$("#clickable a").click(function(e) {
   // Do something
   e.stopPropagation();
});

3
すばらしい答えです。オプションもあります。
Jonathon Watney

4
+1!stopPropagationを使用してクリックハンドラーをアタッチすることは、非常に優れたトリックです。
Thomas

2
伝播を防止したい要素がたくさんある場合は、その親要素を見つけて、そこから泡立つのを防ぐことができます。たとえば、div内のすべてのaリンクをインターセプトするのではなく、たとえば、div自体のクリックをインターセプトし、それ以上高くならないようにして、設定します。
2012年

21
他の誰かがハンドラーを子にアタッチするかどうか、またはライブラリーがハンドラーを子にアタッチする必要があるかどうか(そして、ライブラリーコードをいじりたくない)かどうかわからないためif( e.target !== this) return;、親で使用する方がe.stopPropagation()子で使用するよりも優れています。それは、懸念のより良い分離です。
UTF_or_Death

3
置くif( e.target !== this) return;自分自身のハンドラをonClickの持たない親の他の子供たちのいずれかがクリックされた場合、その後、何も起こらないことを親手段でチェックを。そのため、たとえばクリック可能な親divがある場合は役に立ちません。e.stopPropagation()ただし、正常に動作します。
derf26

100

stopPropagationメソッドを使用します。例を参照してください。

$("#clickable a").click(function(e) {
   e.stopPropagation();
});

jQuery Docsによると:

stopPropagation メソッドは、イベントがDOMツリーを泡立たせないようにし、親ハンドラーにイベントが通知されないようにします。

それはしないことに注意してください、このイベント処理するために、他の人のリスナーを防ぐことが望ましい効果ではない場合、あなたが使用する必要があり、(ボタンの例:複数のクリックハンドラを)stopImmediatePropagation代わりに。


48

ここで、jQuery以外のコード(純粋なJavaScript)を探しているすべての人のための私の解決策

document.getElementById("clickable").addEventListener("click", function( e ){
    e = window.event || e; 
    if(this === e.target) {
        // put your code here
    }
});

親の子をクリックしても、コードは実行されません


1
これは私にとってうまくいきました、私は非JS / jQueryソリューションが必要でした。10倍!
LA

すばらしい答えです。イベントに直接合格しました。そのためwindow.event、MDNが推奨しないを使用しませんでした:developer.mozilla.org/en-US/docs/Web/API/Window/event。時間に余裕があれば、なぜ使用したのかコメントしていただければ幸いですwindow.event(多分それは2015年に存在した問題か、理由を理解できなかったためです)。
RMo

15

あなたもこれを試すことができます

$("#clickable").click(function(event) {
   var senderElementName = event.target.tagName.toLowerCase();
   if(senderElementName === 'div')
   {
       // do something here 
   } 
   else
   {
      //do something with <a> tag
   }
});

14

いずれにせよ内部要素と対話するつもりがない場合は、CSSソリューションが役立つ場合があります。

内部要素を次のように設定するだけです pointer-events: none

あなたの場合:

.clickable > a {
    pointer-events: none;
}

または、一般的にすべての内部要素をターゲットにするには:

.clickable * {
    pointer-events: none;
}

この簡単なハックにより、ReactJSでの開発中に多くの時間を節約できました

ブラウザのサポートはここにあります:http : //caniuse.com/#feat=pointer-events



8

return false;またはe.stopPropogation();を使用すると、さらにコードを実行できなくなります。この時点でフローが停止します。


はい、これは重要です-自分でこれに遭遇しました。しかし、Rexからの上記の回答は役に立ちます。クリックされた要素を取得でき、場合によっては、停止しようとしているロジックでこれを使用できます。.target.nodeNameは、何がヒットしたかを明確に理解するのにも役立ちました。
ウォーターケイマン


4

インライン代替:

<div>
    <!-- Other content. -->
    <a onclick='event.stopPropagation();' href="http://foo.com">I don't want #clickable to handle this click event.</a>
</div>

3

これはAngular 2+を使用した例です

たとえば、ユーザーがモーダルコンポーネントの外側をクリックした場合にそれを閉じる場合:

// Close the modal if the document is clicked.

@HostListener('document:click', ['$event'])
public onDocumentClick(event: MouseEvent): void {
  this.closeModal();
}

// Don't close the modal if the modal itself is clicked.

@HostListener('click', ['$event'])
public onClick(event: MouseEvent): void {
  event.stopPropagation();
}


1

var inner = document.querySelector("#inner");
var outer = document.querySelector("#outer");
inner.addEventListener('click',innerFunction);
outer.addEventListener('click',outerFunction);

function innerFunction(event){
  event.stopPropagation();
  console.log("Inner Functiuon");
}

function outerFunction(event){
  console.log("Outer Functiuon");
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Pramod Kharade-Event with Outer and Inner Progration</title>
</head>
<body>
<div id="outer" style="width:100px;height:100px;background-color:green;">
  <div id="inner" style="width:35px;height:35px;background-color:yellow;"></div>
</div>
</body>
</html>


0

サブ要素をクリック不可として指定するには、以下の例のようにcss階層を記述します。

この例では、クラス ".subtable"を持つテーブル内のtr内のtd内のすべての要素(*)への伝播を停止します

$(document).ready(function()
{    
   $(".subtable tr td *").click(function (event)
   {
       event.stopPropagation();
   });

});

0

ignoreParent()は純粋なJavaScriptソリューションです。

これは、マウスクリックの座標を子要素の座標と比較する中間レイヤーとして機能します。2つの簡単な実装手順:

1.ページにignoreParent()コードを配置します。

2.親の元のonclick = "parentEvent();"の代わりに 、 書く:

onclick="ignoreParent(['parentEvent()', 'child-ID']);"

任意の数の子要素のIDを関数に渡し、他の要素を除外することができます。

子要素の1つをクリックした場合、親イベントは発生しません。親をクリックしたが、子要素[引数として提供]をクリックしなかった場合、親イベントが発生します。

GithubのignoreParent()コード


0

インラインコンテキストの場合、HTMLでこれを試してください。

onclick="functionCall();event.stopPropagation();

-1

誰かがReactを使用してこの問題を抱えていた場合、これが私がそれを解決した方法です。

scss:

#loginBackdrop {
position: absolute;
width: 100% !important;
height: 100% !important;
top:0px;
left:0px;
z-index: 9; }

#loginFrame {
width: $iFrameWidth;
height: $iFrameHeight;
background-color: $mainColor;
position: fixed;
z-index: 10;
top: 50%;
left: 50%;
margin-top: calc(-1 * #{$iFrameHeight} / 2);
margin-left: calc(-1 * #{$iFrameWidth} / 2);
border: solid 1px grey;
border-radius: 20px;
box-shadow: 0px 0px 90px #545454; }

コンポーネントのrender():

render() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

子モーダル(コンテンツdiv)のonClick関数を追加することにより、マウスクリックイベントが親要素の「closeLogin」関数に到達するのを防ぎます。

これでうまくいきました。2つのシンプルなdivでモーダルエフェクトを作成できました。


-3

a次のように追加します。

<a href="http://foo.com" onclick="return false;">....</a>

またはreturn false;クリックハンドラーからの#clickableように:

  $("#clickable").click(function() {
        var url = $("#clickable a").attr("href");
        window.location = url;
        return false;
   });

-3

すべてのソリューションは複雑でjscriptです。これが最も単純なバージョンです。

var IsChildWindow=false;

function ParentClick()
{
    if(IsChildWindow==true)
    {
        IsChildWindow==false;
        return;
    }
    //do ur work here   
}


function ChildClick()
{
    IsChildWindow=true;
    //Do ur work here    
}

3
「IsChildWindow == false;」の行を間違えたと思います。-「IsChildWindow = false;」にすべきではありませんか?
Andre Schweighofer 2012年

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.