Bootstrap的accordion header里面的元素click无法用event.stopPropagation阻止accordion的事件


案例一: accordion header里面的link无法点开,事件被accordion的 expanding/collapsing响应了。
I am trying to add an external link to a bootstrap accordion header using stopPropagation on the click event.
Unfortunately, the link is not working and the expanding/collapsing of the accordion still happens.

html:

<ul class="accordion" id="collapse1">
  <li>
    <div class="accordion-button collapsed" href="#one" 
         data-bs-toggle="collapse" data-bs-target="#one" aria-expanded="false">
         Maincategory
         &nbsp;/&nbsp;
         <a href="https://google.com" class="non-collapsing">
           open
         </a>
    </div>
    <ul class="accordion-collapse collapse" id="one" data-bs-parent="#collapse1">
      <li><a href="#">Sub 1</a></li>
      <li><a href="#">Sub 2</a></li>
      <li><a href="#">Sub 3</a></li>
    </ul>
  </li>
</ul>

js:

$('.non-collapsing').on('click', function (e) {
    e.stopPropagation();
});

案例二: headerl里面的javascript事件被执行,同时expanding/collapsing也被执行。
h2.accordion-header id="flush-heading#{word.id}"
  button.accordion-button.collapsed type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapse#{word.id}" aria-expanded="fa    lse" aria-controls="flush-collapse#{word.id}"
    span 
      span.me-2.fw-bold=word.name
      span=link_to "###", class: "operate-word-sound badge rounded-pill bg-secondary non-collapsing", "data-sound-text": "#{word.name}",     'data-bs-toggle': "collapse", "data-bs-target": "#flush-collapse"
        i class="fa-solid fa-volume-low"
.accordion-collapse.collapse id="flush-collapse#{word.id}" aria-labelledby="flush-heading#{word.id}" data-bs-parent="#accordionFlushWord    "
  div
    something here...

js:
document.querySelectorAll('.operate-word-sound').forEach(function(wordBtn) {
    wordBtn.addEventListener('click', function(event) {
       let word =  wordBtn.dataset.soundText
       let url = "someurl here"+ word
       let audio = new Audio(url)      
      audio.addEventListener("canplaythough", event => {
         /* 音频可以播放;如果权限允许则播放 */
        audio.play();
      });

      //console.log(event.eventPhase)
      //event.preventDefault();
      event.stopPropagation();       //完全无法阻止事件冒泡给他的父元素
      //event.stopImmediatePropagation();

   })
})

为什么会这样?
我也不知道具体的原因是什么,不过可以推测的是,他们可能不属于一个事件体系,不在同一条事件线上。
就好像你在上游拦截,可是他不在你的下游,你拦截了一个寂寞。
就好像张三在A国说了些不当的话,然后拦截A国的所有媒体,但是没有拦截住,因为在A国的张三的言论发布在B国。那现在就需要直接让张三闭嘴。

怎么解决?
Adding data-bs-toggle="collapse" and an empty data-bs-target to the link element worked for me. (works also with a <button> instead of <a>)

<ul class="accordion" id="collapse1">
  <li>
    <div class="accordion-button collapsed" href="#one" 
         data-bs-toggle="collapse" data-bs-target="#one" aria-expanded="false">
         Maincategory
         &nbsp;/&nbsp;
         <a href="https://google.com" class="non-collapsing" data-bs-toggle="collapse" data-bs-target>
           open
         </a>
    </div>
    <ul class="accordion-collapse collapse" id="one" data-bs-parent="#collapse1">
      <li><a href="#">Sub 1</a></li>
      <li><a href="#">Sub 2</a></li>
      <li><a href="#">Sub 3</a></li>
    </ul>
  </li>
</ul>


改造一下这个link。让这个link的data-bs-target指向一个不存在的元素。就好比把言论发不出去一样了。

The data-bs-toggle="collapse" data-bs-target works perfectly. 
备注: the non-collapsing class and associated JS in the fiddle are not needed, they are only there because they were part of the original fiddle by OP.
阅读量: 799
发布于:
修改于: