最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Stop parent event firing on child element click - Stack Overflow

programmeradmin1浏览0评论

I have a click event on li tag and then in that li i have another nested li.

When clicked on parent li everything works fine. But onclick nested or child li the parent li click event is fired.

I have used event.stopPropagation() method but it does not work in my case.

$("li").on("click",function() {
  console.log(this.firstChild.textContent)
})
$('#testUl > li').on('click', function(e) {
  e.stopPropagation();
})
<script src=".6.0/jquery.min.js"></script>
<ul id="testUl">
  <li>
    <a href="#">Test A</a>
    <div class="innerUl">
      <ul>
        <li>Inner A</li>
        <li>Inner B</li>
        <li>Inner C</li>
      </ul>
    </div>
  </li>
</ul>

I have a click event on li tag and then in that li i have another nested li.

When clicked on parent li everything works fine. But onclick nested or child li the parent li click event is fired.

I have used event.stopPropagation() method but it does not work in my case.

$("li").on("click",function() {
  console.log(this.firstChild.textContent)
})
$('#testUl > li').on('click', function(e) {
  e.stopPropagation();
})
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<ul id="testUl">
  <li>
    <a href="#">Test A</a>
    <div class="innerUl">
      <ul>
        <li>Inner A</li>
        <li>Inner B</li>
        <li>Inner C</li>
      </ul>
    </div>
  </li>
</ul>

Share Improve this question edited Nov 10, 2021 at 12:16 mplungjan 178k28 gold badges182 silver badges240 bronze badges asked Nov 10, 2021 at 12:10 ShakirShakir 1031 silver badge10 bronze badges 4
  • $('#testUl > li') is probably the wrong selector. If you want the same function for parent and children: $('#testUI li') – Dov Rine Commented Nov 10, 2021 at 12:13
  • Your code has the stopPropagation on the parent element. Child elements get click events first. This is assuming you have a second event on the child li, not included in your question. Otherwise there's only a parent event anyway. – fdomn-m Commented Nov 10, 2021 at 12:13
  • I made you a snippet. Please add YOUR function that you do not want executed – mplungjan Commented Nov 10, 2021 at 12:17
  • (note: 2nd event was added via edit, needs to be updated by OP, via an edit) – fdomn-m Commented Nov 10, 2021 at 12:27
Add a ment  | 

4 Answers 4

Reset to default 3

Without jQuery you can use event delegation and determine to act using Element.closest()

document.addEventListener(`click`, handle);

function handle(evt) {
  console.clear();
  
  if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
      console.log(`You clicked (something within) the first li of ul#testUl`);
  }
}
<ul id="testUl">
  <li>
    <a href="#">Test A</a>
    <div class="innerUl">
      <ul>
        <li>Inner A</li>
        <li>Inner B</li>
        <li>Inner C</li>
      </ul>
    </div>
  </li>
</ul>

Same idea with jQuery

$("#testUl").on("click", evt => {
    console.clear();
    if (!evt.target.closest(`.innerUl`) && evt.target.closest(`#testUl`)) {
      console.log(`You clicked ${evt.target.outerHTML}`);
    }
  });
<script 
  src="https://cdnjs.cloudflare./ajax/libs/jquery/3.6.0/jquery.min.js">
</script>

<ul id="testUl">
  <li>
    <a href="#">Test A</a>
    <div class="innerUl">
      <ul>
        <li>Inner A</li>
        <li>Inner B</li>
        <li>Inner C</li>
      </ul>
    </div>
  </li>
</ul>

$('#testUl .innerUl li').on('click', function(e) {
    e.stopPropagation();
});

// or 
$('#testUl li').on('click', function(e) {
    e.stopPropagation();
});

$('#testUl > li').on('click', function(e) {
   alert('test');
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- #testUl -->
<ul id="testUl">
    <!-- #testUl > li -->
    <li>
        <!-- #testUl > li > a or #testUl a -->
        <a href="#">Test A</a>
        <!-- #testUl > li > .innerUl or #testUl .innerUl -->
        <div class="innerUl">
            <!-- #testUl > li > .innerUl > ul or #testUl ul -->
            <ul>
                <!-- #testUl > li > .innerUl > ul > li or #testUl li or #testUl .innerUl li or .innerUl li -->
                <li>Inner A</li>
                <li>Inner B</li>
                <li>Inner C</li>
            </ul>
        </div>
    </li>
</ul>

You are using a wrong selector for stop propagation

When you use #testUl > li you call the first li child element, but you have li elements inside your li on #testUl, so call #testUl li or #testUl .innerUl li

You can pare e.target which is element that have click event and e.currentTarget that is element you actually clicked. If they don't match then you return without performing rest of function

$('#testUl > li').on('click', (e) => {
    if (e.target !== e.currentTarget) {
        return;
    }
    console.log('parent');
});

$('.innerUl li').on('click', (e) => {
    if (e.target !== e.currentTarget) {
        return;
    }
    console.log('child');
});
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="testUl">
    <li>
        Test A
        <div class="innerUl">
            <ul>
                <li>Inner A</li>
                <li>Inner B</li>
                <li>Inner C</li>
            </ul>
        </div>
    </li>
</ul>

You can try with stopImmediatePropagation()

See here: https://developer.mozilla/en-US/docs/Web/API/Event/stopImmediatePropagation

发布评论

评论列表(0)

  1. 暂无评论