Làm thế nào để có sự kiện click CHỈ bắn vào cha mẹ DIV chứ không phải con?


211

Tôi có một DIV với một lớp được phân loại foobarvà một vài DIV bên trong DIV đó không được phân loại, nhưng tôi cho rằng chúng đang kế thừa foobarlớp:

$('.foobar').on('click', function() { /*...do stuff...*/ });

Tôi muốn điều đó chỉ tắt khi nhấp vào một nơi nào đó trong DIV chứ không phải trên các DIV con của nó.

Câu trả lời:


439

Nếu e.targetlà phần tử giống như this, bạn đã không nhấp vào một hậu duệ.

$('.foobar').on('click', function(e) {
  if (e.target !== this)
    return;
  
  alert( 'clicked the foobar' );
});
.foobar {
  padding: 20px; background: yellow;
}
span {
  background: blue; color: white; padding: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='foobar'> .foobar (alert) 
  <span>child (no alert)</span>
</div>


Câu trả lời đó giải thích nhận xét này
gdoron đang hỗ trợ Monica

@gdoron: Adam quá tử tế. :)

1
Xin chào @vicky. Chỉ cần FYI, JavaScript có hai loại so sánh bình đẳng giá trị khác nhau. Các ===hoặc !==sử dụng các "Strict Bình đẳng So sánh thuật toán" , trong khi ==!=sử dụng các "Tóm tắt bình đẳng So sánh thuật toán" , đó là loại cưỡng chế. Sự khôn ngoan chung là luôn luôn sử dụng so sánh chặt chẽ trừ khi có nhu cầu cụ thể đối với loại cưỡng chế (vì quy tắc của nó hơi phức tạp) . Trong trường hợp này, vì các đối tượng đang được so sánh, nó thực sự không tạo ra sự khác biệt, nhưng bạn sẽ thấy rằng hầu hết mọi người vẫn sẽ gắn bó với sự so sánh nghiêm ngặt .

1
@vicky: Không sao đâu. Nó vẫn đúng. Chỉ cần cho phép bạn có các toán tử khác nhau. ;-)

3
Đây là một câu trả lời tốt vì nó cũng có thể hoạt động với Vanilla JS addEventListener và không phải là jQuery cụ thể.
Michael Giovanni Pumo

64

Có một cách khác hoạt động nếu bạn không chỉ nhắm mục tiêu các trình duyệt mới hơn. Chỉ cần thêm CSS

pointer-events: none;

cho bất kỳ đứa trẻ nào của div mà bạn muốn chụp. Đây là bảng hỗ trợ

http://caniuse.com/#feat=pulum-events


13
Biết rằng tôi nên tránh viết bình luận 'cảm ơn', nhưng tôi có thể hôn bạn vì điều này :-)
Simona Adriani

@SimonaAdriani hả?
n3wb

Cảm ơn, tôi đã làm theo cách tương tự, nhưng tôi đang vật lộn để viết trường hợp kiểm tra đơn vị xung quanh nó. Làm thế nào tôi có thể đảm bảo clickkích hoạt sự kiện nhấp chuột theo chương trình?
Pankaj Parkar

29

Bạn có thể sử dụng bong bóng có lợi cho bạn:

$('.foobar').on('click', function(e) {
    // do your thing.
}).on('click', 'div', function(e) {
    // clicked on descendant div
    e.stopPropagation();
});

Đây có vẻ là một giải pháp tốt cho kịch bản cụ thể của tôi, vì tôi chỉ muốn loại trừ các nhấp chuột vào <a>các yếu tố hậu duệ . Chỉ có một vấn đề: Khi tôi nhấp chuột vào chúng, sự kiện vẫn kích hoạt (được thử nghiệm trong Google Chrome). Có một biến thể của điều này cũng ngăn chặn điều này?
cgogolin

@cgogolin, hãy xem cái này: stackoverflow.com/questions/12197122/
Jessica

28

Tôi đã không nhận được câu trả lời được chấp nhận để làm việc, nhưng điều này dường như thực hiện mánh khóe, ít nhất là trong vanilla JS.

if(e.target !== e.currentTarget) return;

1
e.cienTarget chính xác hơn tham chiếu thisvì đối tượng thisđược trỏ đến có thể thay đổi tùy thuộc vào phạm vi và bối cảnh từ nơi nó được gọi
eballeste

20
//bind `click` event handler to the `.foobar` element(s) to do work,
//then find the children of all the `.foobar` element(s)
//and bind a `click` event handler to them that stops the propagation of the event
$('.foobar').on('click', function () { ... }).children().on('click', function (event) {
    event.stopPropagation();
    //you can also use `return false;` which is the same as `event.preventDefault()` and `event.stopPropagation()` all in one (in a jQuery event handler)
});

Điều này sẽ ngăn sự lan truyền (sủi bọt) của clicksự kiện trên bất kỳ phần tử con nào của (các) .foobarphần tử để sự kiện không đến được .foobarphần tử để xử lý (các) phần tử xử lý sự kiện của chúng.

Đây là bản demo: http://jsfiddle.net/bQQJP/


3
$(".advanced ul li").live('click',function(e){
    if(e.target != this) return;
    //code
    // this code will execute only when you click to li and not to a child
})

2

Tôi đã có cùng một vấn đề và đưa ra giải pháp này (dựa trên các câu trả lời khác)

 $( ".newsletter_background" ).click(function(e) {
    if (e.target == this) {
        $(".newsletter_background").hide();
    } 
});

Về cơ bản nó nói nếu mục tiêu là div thì hãy chạy mã nếu không làm gì cả (đừng ẩn nó)


1

Trường hợp của tôi cũng tương tự nhưng đây là dịp bạn có vài foobargiây và bạn chỉ muốn đóng một - mỗi lần nhấp:

Tìm trường hợp cha mẹ

$(".foobar-close-button-class").on("click", function () {
    $(this).parents('.foobar').fadeOut( 100 );
    // 'this' - means that you finding some parent class from '.foobar-close-button-class'
    // '.parents' -means that you finding parent class with name '.foobar'
});

Tìm trường hợp con

$(".foobar-close-button-class").on("click", function () {
    $(this).child('.foobar-close-button-child-class').fadeOut( 100 );
    // 'this' - means that you finding some child class from '.foobar-close-button-class'
    // '.child' -means that you finding child class with name '.foobar-close-button-child-class'
});

1

Bạn có thể sử dụng event.cienTarget. Nó sẽ làm click click chỉ elemnt ai có sự kiện.

target = e => {
    console.log(e.currentTarget);
  };
<ul onClick={target} className="folder">
      <li>
        <p>
          <i className="fas fa-folder" />
        </p>
      </li>
    </ul>


1

Nếu bạn không thể sử dụng pointer-events: none;và đang nhắm mục tiêu các trình duyệt hiện đại, bạn có thể sử dụng composedPathđể phát hiện nhấp chuột trực tiếp vào đối tượng như vậy:

element.addEventListener("click", function (ev) {
    if (ev.composedPath()[0] === this) {
        // your code here ...
    }
})

Bạn có thể đọc thêm về compPath tại đây: https://developer.mozilla.org/en-US/docs/Web/API/Event/composesPath


0

// if its li get value 
document.getElementById('li').addEventListener("click", function(e) {
                if (e.target == this) {
                    UodateNote(e.target.id);
                }
                })
                
                
                function UodateNote(e) {

    let nt_id = document.createElement("div");
    // append container to duc.
    document.body.appendChild(nt_id);
    nt_id.id = "hi";
    // get conatiner value . 
    nt_id.innerHTML = e;
    // body...
    console.log(e);

}
li{
 cursor: pointer;
    font-weight: bold;
  font-size: 20px;
    position: relative;
    width: 380px;
    height: 80px;
    background-color: silver;
    justify-content: center;
    align-items: center;
    text-align: center;
    margin-top: 0.5cm;
    border: 2px solid purple;
    border-radius: 12%;}
    
    p{
     cursor: text;
  font-size: 16px;
   font-weight: normal;
    display: block;
    max-width: 370px;
    max-height: 40px;
    overflow-x: hidden;}
<li id="li"><p>hi</p></li>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.