ฉันจะป้องกันไม่ให้เหตุการณ์ onclick ของผู้ปกครองยิงเมื่อผู้ประกาศข่าวเด็กถูกคลิกได้อย่างไร


348

ฉันกำลังใช้ jQuery เพื่อให้สามารถคลิก div ได้และใน div นี้ฉันยังมีเบรก ปัญหาที่ฉันพบคือเมื่อฉันคลิกที่จุดยึดทั้งเหตุการณ์การคลิกกำลังเริ่มทำงาน (สำหรับ div และตัวยึด) ฉันจะป้องกันไม่ให้เหตุการณ์ onclick ของ div ไม่ทำงานเมื่อคลิกสมอ

นี่คือรหัสที่ใช้ไม่ได้:

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>

คำตอบ:


460

เหตุการณ์ฟองสบู่ถึงจุดสูงสุดใน DOM ที่แนบเหตุการณ์การคลิก ดังนั้นในตัวอย่างของคุณแม้ว่าคุณจะไม่มีองค์ประกอบอื่น ๆ ที่สามารถคลิกได้อย่างชัดเจนใน div องค์ประกอบย่อย ๆ ของ div จะทำให้เหตุการณ์การคลิกของพวกเขาเพิ่มขึ้นเป็น DOM จนกระทั่งตัวจัดการเหตุการณ์คลิกของ DIV จับได้

มีสองวิธีในการแก้ไขปัญหานี้คือการตรวจสอบว่าใครเป็นผู้สร้างเหตุการณ์จริง 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 เป็นคำแนะนำที่ดีมากขอบคุณ!
โทมัส

2
หากคุณมีองค์ประกอบหลายอย่างที่คุณต้องการป้องกันไม่ให้เผยแพร่คุณสามารถค้นหาองค์ประกอบหลักของพวกเขาและหัวป้องกันไม่ให้มันเดือดปุด ๆ ที่นั่น ดังนั้นแทนที่จะขัดขวางลิงก์ทั้งหมดใน div ตัวอย่างเช่น - เพียงแค่ตัดการคลิกแม้กระทั่งใน div และป้องกันไม่ให้มันไปสูงกว่านี้อีกแล้วและคุณตั้งค่าไว้
sucitivel

21
การใช้if( e.target !== this) return;ในพาเรนต์นั้นดีกว่าe.stopPropagation()ในเด็กเพราะคุณไม่เคยรู้เลยว่ามีคนอื่นแนบ handler กับเด็กหรือว่าห้องสมุดจะต้องแนบ handler กับเด็ก (และคุณไม่ต้องการยุ่งกับรหัสห้องสมุด) มันเป็นการแยกความกังวลที่ดีกว่า
UTF_or_Death

3
การวางการif( e.target !== this) return;ตรวจสอบในพาเรนต์หมายความว่าหากมีลูกอื่น ๆ ของพาเรนต์ที่ไม่มีตัวจัดการ onClick ของตนเองถูกคลิกแล้วไม่มีอะไรเกิดขึ้น ดังนั้นจึงไม่มีประโยชน์สำหรับสถานการณ์ที่คุณมีเช่นผู้ปกครองที่คลิกได้ e.stopPropagation()ทำงานได้ดี แต่
derf26

101

ใช้เมธอดstopPropagationดูตัวอย่าง:

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

ดังที่ได้กล่าวไว้โดย jQuery Docs:

stopPropagation วิธีการป้องกันเหตุการณ์จากการเดือดปุด ๆ ขึ้นต้นไม้ DOM ป้องกันไม่ให้ตัวจัดการผู้ปกครองใด ๆ จากการได้รับแจ้งของเหตุการณ์

โปรดทราบว่ามันไม่ได้ป้องกันผู้ฟังคนอื่น ๆ ที่จะจัดการกับเหตุการณ์นี้ (เช่นตัวจัดการคลิกมากกว่าหนึ่งปุ่ม) ถ้ามันไม่ใช่เอฟเฟกต์ที่ต้องการคุณต้องใช้stopImmediatePropagationแทน


48

นี่คือทางออกของฉันสำหรับทุกคนที่นั่นมองหารหัสที่ไม่ใช่ jQuery (pure 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.eventMDN ตัวไหนที่ท้อ: 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 อาจเป็นประโยชน์สำหรับคุณ

เพียงตั้งองค์ประกอบภายใน / s เป็น pointer-events: none

ในกรณีของคุณ:

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

หรือกำหนดเป้าหมายองค์ประกอบภายในทั้งหมดโดยทั่วไป:

.clickable * {
    pointer-events: none;
}

แฮ็คที่ง่ายนี้ช่วยฉันประหยัดเวลาได้มากในขณะที่พัฒนาด้วย ReactJS

พบการสนับสนุนเบราว์เซอร์ที่นี่: http://caniuse.com/#feat=pointer-events


8

หากคุณมีหลายองค์ประกอบใน div ที่คลิกได้คุณควรทำสิ่งนี้:

$('#clickable *').click(function(e){ e.stopPropagation(); });

8

การใช้return false;หรือe.stopPropogation();ไม่อนุญาตให้ใช้รหัสเพิ่มเติมเพื่อดำเนินการ มันจะหยุดไหลที่จุดนี้เอง


ใช่นี่เป็นสิ่งสำคัญ - วิ่งเข้าไปหาตัวเอง แต่คำตอบข้างต้นจาก Rex มีประโยชน์ - สามารถรับองค์ประกอบที่ถูกคลิกและในบางกรณีใช้สิ่งนี้ในตรรกะที่คุณพยายามหยุด .target.nodeName ก็มีประโยชน์เช่นกันในการรับทราบข้อมูลที่ชัดเจนเกี่ยวกับสิ่งที่ได้รับผลกระทบ
Watercayman



3

นี่คือตัวอย่างการใช้ Angular 2+

ตัวอย่างเช่นหากคุณต้องการปิด Modal Component หากผู้ใช้คลิกที่ด้านนอก:

// 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

คุณต้องหยุดกิจกรรมจากการเข้าถึง (เดือดดาล) ผู้ปกครอง (div) ดูส่วนที่เกี่ยวกับเดือดปุด ๆที่นี่และข้อมูล API jQuery เฉพาะที่นี่


เย็น. ขอบคุณสำหรับข้อมูลเกี่ยวกับเหตุการณ์เดือดปุด ๆ
Jonathon Watney

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 ดังตัวอย่างด้านล่าง

ในตัวอย่างนี้ฉันหยุดการเผยแพร่ไปยังองค์ประกอบใด ๆ (*) ภายใน td ภายใน tr ภายในตารางที่มีคลาส ".subtable"

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

});

0

ละเว้นParent ()เป็นโซลูชัน JavaScript ที่แท้จริง

มันทำหน้าที่เป็นตัวกลางเลเยอร์ที่เปรียบเทียบพิกัดของการคลิกเมาส์กับพิกัดขององค์ประกอบย่อย / s สองขั้นตอนการติดตั้งง่าย:

1ใส่โค้ด ignParent () บนหน้าของคุณ

2.แทนที่จะเป็นต้นฉบับของผู้ปกครองonclick = "parentEvent ();" เขียน:

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

คุณสามารถส่ง ID ขององค์ประกอบลูกจำนวนใดก็ได้ไปยังฟังก์ชั่นและไม่รวมองค์ประกอบอื่น ๆ

หากคุณคลิกที่องค์ประกอบย่อยหนึ่งรายการกิจกรรมหลักจะไม่เริ่มทำงาน หากคุณคลิกที่ผู้ปกครอง แต่ไม่ได้อยู่ในองค์ประกอบลูกใด ๆ [ให้เป็นข้อโต้แย้ง] เหตุการณ์ผู้ปกครองจะถูกยิง

โค้ด ignParent () บน Github


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() {
    ...
    return (
        <div id='loginBackdrop' onClick={this.props.closeLogin}>
            <div id='loginFrame' onClick={(e)=>{e.preventDefault();e.stopPropagation()}}>
             ... [modal content] ...
            </div>
        </div>
    )
}

โดยการเพิ่มฟังก์ชั่น onClick สำหรับเหตุการณ์การคลิกเมาส์ลูกโมดอล (เนื้อหา div) ถูกป้องกันไม่ให้เข้าถึงฟังก์ชั่น 'closeLogin' ขององค์ประกอบหลัก

นี่เป็นกลอุบายสำหรับฉันและฉันก็สามารถสร้างเอฟเฟกต์แบบโมดัลด้วย 2 div ง่าย ๆ


-3

เพิ่มaดังนี้:

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

หรือreturn false;จากตัวจัดการคลิกเพื่อกด#clickablelike:

  $("#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

-5
<a onclick="return false;" href="http://foo.com">I want to ignore my parent's onclick event.</a>

5
สิ่งนี้ยังป้องกันไม่ให้ลิงก์จากการนำทาง
Rex M

ใช่หรือไม่ใช่สิ่งที่จำเป็น? หรือจะต้องเป็น nevegar?
andres descalzo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.