【问题标题】:Always select a parent element when clicking on a child单击子元素时始终选择父元素
【发布时间】:2015-10-07 10:03:13
【问题描述】:

我有一个 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 中有一个单击事件,为新选项卡提供 chat-tab-sel 类并从旧选项卡中删除此类(标准选项卡行为)。

我的问题是,根据用户点击的位置,我的 event.target 并不总是父 div chat-tab,而是子 span 之一。我需要向父 div 添加/删除类。

我认为如果父母有display: block 它可能会工作,但在这种情况下我需要它是display: flex 因为在孩子身上有灵活的宽度是有意义的。

那么:当用户点击一个孩子时,是否可以确保父 div 被定位?

【问题讨论】:

  • $( event.target ).closest( ".chat-tab" ) 应该可以为您提供所需的内容。
  • 您可以在子跨度上尝试 pointer-events: none; 的 css 样式。也许只有父 div 会注册点击。 (不确定这是否可行)
  • 显示切换类的事件处理程序代码。

标签: javascript html css meteor click


【解决方案1】:

如果您将普通的 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
  }
});

【讨论】:

    【解决方案2】:

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

    不确定 Meteor 的具体情况,但这是我使用原生 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>

    【讨论】:

      【解决方案3】:

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

      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

      假设你有这个 HTML 结构:

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

      事件委托不是浏览器功能,而是内置于 jQuery 等库中的流行技术。许多博客在谈论它或将其等同于冒泡时感到困惑,但我希望以下描述清楚。

      假设您想要响应对页面上任何 A 标记的点击,即使 A 标记集随时间而变化。特别是,您不想访问每个 A 标记并添加事件侦听器。因此,利用冒泡,您将单个事件处理程序绑定到 BODY,并从该处理程序中查看 event.target 以查看是否单击了 A,如果是,是哪个。不过要小心,因为 event.target 可能是 SPAN!您不仅需要检查事件的目标是否是 A 标记,还需要在冒泡的简单模拟中向上遍历 DOM 树。

      这是事件委托。 BODY 元素是代表 A 标记处理事件的委托。从概念上讲,我们希望将事件处理程序视为位于 A 标记上,因此我们尽可能多地创建这种错觉。为此,事件委托的最后一步(至少在 jQuery 和 Meteor 中)是将 event.currentTarget 设置为 A 标签。 处理该事件的其他代码将 A 标记视为 currentTarget,将 SPAN 标记视为目标。 BODY 元素并不是很重要,所以无处可寻。

      【讨论】:

        猜你喜欢
        • 2016-11-08
        • 1970-01-01
        • 1970-01-01
        • 2012-05-03
        • 2019-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多