单击 child 时总是 select parent 元素

Always select a parent element when clicking on a child

我有一个 div(标签),里面有 3 个跨度,像这样:

<div class="chat-tabs">
    <div class="chat-tabs-cont">
        <div id="chat-tab-1" class="chat-tab chat-tab-sel">
            <span class="chat-tab-n">1</span>
            <span class="chat-tab-t">Tab text 1</span>
            <span class="chat-tab-c">11:00</span>
        </div>
        <div id="chat-tab-2" class="chat-tab">
            <span class="chat-tab-n">2</span>
            <span class="chat-tab-t">Tab text 2</span>
            <span class="chat-tab-c">11:30</span>
        </div>
    </div>
</div>

这些是选项卡,所以当我单击一个选项卡时,我在 Meteor 中有一个单击事件,为新选项卡提供 class 的 chat-tab-sel 并从中删除此 class旧选项卡(标准选项卡行为)。

我的问题是,根据用户点击的位置,我的 event.target 并不总是 parent div chat-tab,而是 child span。我需要 add/remove classes 到 parent div.

我认为如果 parent 有 display: block 它可能会起作用,但在这种情况下我需要它是 display: flex 因为在 [=32 上有灵活的宽度是有意义的=]s.

所以:是否可以确保当用户点击 child 时 parent div 是有针对性的?

事件气泡。这意味着您可以监听父级上的事件。在事件侦听器中,this 绑定到您将事件侦听器绑定到的元素。所以我们可以监听该元素内的任何点击,然后将当前活动选项卡设置为非活动状态,并将单击的选项卡设置为活动状态。

具体不确定 Meteor,但这就是我使用 vanilla JavaScript.

完成此操作的方式

var tabs = document.querySelectorAll('.chat-tab');

for(var i in Object.keys(tabs)) tabs[i].onclick = function() {
    document.querySelector('.chat-tab.chat-tab-sel').className = 'chat-tab';
    this.className += ' chat-tab-sel'
}
.chat-tab-sel {
  border: 1px solid #012450;
}
<div class="chat-tabs">
    <div class="chat-tabs-cont">
        <div id="chat-tab-1" class="chat-tab chat-tab-sel">
            <span class="chat-tab-n">1</span>
            <span class="chat-tab-t">Tab text 1</span>
            <span class="chat-tab-c">11:00</span>
        </div>
        <div id="chat-tab-2" class="chat-tab">
            <span class="chat-tab-n">2</span>
            <span class="chat-tab-t">Tab text 2</span>
            <span class="chat-tab-c">11:30</span>
        </div>
    </div>
</div>

如果您将普通的 Meteor 事件处理程序与@Brian Shamblen 的提示结合使用,它应该可以正常工作。

Template.myTemplate.events({
  'click .chatTab': function(ev){
    $(".chat-tab").removeClass("chat-tab-sel"); // remove from all
    $(ev.target).closest(".chat-tab").addClass("chat-tab-sel"); // set the one you're on
  }
});

基于 Tiny Giant 对事件冒泡的回答,这里是在 meteor 中执行此操作:

Template.theTemplate.events({
  'click .chat-tab': function(ev) {
    $('.chat-tab').removeClass('chat-tab-sel'); 
    $(ev.currentTarget).addClass('chat-tab-sel');
  }
});

这是一篇有趣的 info.meteor.com 博文,其中对此进行了一些详细介绍:

Browser events: bubbling, capturing, and delegation

Suppose you have this HTML structure:

<body>
  <p>
    <a><span>Hello</span></a>
  </p>
</body>

Event delegation is not a browser feature, but a popular technique built into libraries like jQuery. Many blogs get confused talking about it or equate it with bubbling, but I hope the following description is clear.

Suppose you want to respond to a click on any A tag on the page, even if the set of A tags changes over time. In particular, you don't want to visit every A tag and add an event listener. So, taking advantage of bubbling, you bind a single event handler to the BODY, and from this handler you look at event.target to see if an A was clicked, and if so, which one. Be careful, though, because event.target may be the SPAN! You need to not just check if the event's target is an A tag, but also walk up the DOM tree in a simple simulation of bubbling.

This is event delegation. The BODY element is the delegate that handles events on behalf of the A tags. Conceptually, we'd like to think of the event handler as being on the A tags, so we create that illusion as much as we can. To that end, the final step in event delegation (at least in jQuery and Meteor) is to set event.currentTarget to the A tag. Further code that handles the event then sees an A tag as currentTarget and a SPAN tag as target. The BODY element is not really important, so it is nowhere to be found.