【问题标题】:Data-id attribute not showing up when added to display:none element添加到 display:none 元素时未显示 Data-id 属性
【发布时间】:2020-04-11 04:01:32
【问题描述】:

我正在使用引导弹出窗口构建一个通知弹出窗口。弹出框为每个通知都有一个 div,每个通知都有相同的类(除了文本内容之外相同)。

<% notifs.each do |notif| %>
  <div class="media n-media notif-popup-container notif-display" data-id=<%= notif.id %> >
    Content
  </div>
<% end %>

结果如下:

notif-popup

但是,当我单击任何通知 div(在图片中)时,我的单击侦听器的 $(this) 将始终引用第一个 div。我知道这一点,因为当我打印 ID 时,即使单击第三个通知 div 也会打印第一个通知 div 的 ID。

在其他地方找不到类似的问题。这是相关的jquery代码。我使用 $(body).on("click") 而不是 $(".className").click 因为后者不会附加到所需的 div,因为 div 有 display:none 直到它弹出。

$('body').on("click", ".popover-body .notif-popup-container", function() {
    console.log("notif popup container clicked");

    // prints <div class="media n-media notif-popup-container notif-display"></div> 
    console.log($(this)[0]);

    // prints {}
    console.log($(this).data());

    // prints first element's id
    console.log($('.notif-popup-container').data("id"));

    // prints undefined
    console.log($(this).data("id"));
 })

这是弹出框代码。我注意到 data-id 属性没有显示在 Chrome 开发工具中,仅适用于我的 style="display:none" div。这些 div 被插入到弹出框标题和内容的选项中,因此它们必须被隐藏。

$(document).ready(function(){
  $("#notificationsBell").popover({
    'title' : $('.notifications-title-header').html(), // display:none for html div
    'html' : true,
    'placement' : 'left',
    'content' : $(".notifications-list").html() // display:none for this as well
  });
});

JS 可能会给出一些提示。使用 Rails 构建,但这似乎无关紧要。任何见解都值得赞赏。

编辑:它没有得到第一个 div,它得到了正确的。它只是没有保留 data-id 属性。所以现在我将把它存储在“id”属性中,该属性将显示在 chrome 开发工具上。我仍然想知道为什么 data-id 不显示,而 id 属性显示。

编辑2:这里是相关的html代码:

  <%= link_to "javascript:void(0);", class: "dropdown-toggle", id: "notificationsBell" do %>
    <i class="fa fa-bell dropdown-toggle" aria-hidden="true"></i>
    <span id="notifUnreadCount">
      <%= Notification.unread_count(current_user) %>
    </span>
  <% end %>

  <div style="display:none" class="notifications-title-header" data-id="sup">
    <p class="notifications-title">
      Notifications
      <span class="see-all-notifs"><u><%= link_to "See all", notifications_path %></u></span>
    </p>
  </div>

  <div style="display:none" class="notifications-list">

    <% unread_notifications = Notification.unread_count(current_user) %>
    <% if unread_notifications === 0 %>

      No notifications to display! You are up to date.

    <% else %>
      <% notifs = current_user.notifications.where(read_at: nil).order("created_at DESC") %>
      <% notifs.each do |notif| %>

        <div class="media n-media notif-popup-container notif-display" id=<%= notif.id %> >

          <%= image_tag "bell.svg", class: "notification-icon-small mr-3" %>

          <div class="media-body noti-info">
            <b><p><%= notif.notify_type %></p></b>
            <span class="n-date trans-timestamp dateTime" data-momentiz="(<%= notif.momentize %>)"></span>
            <p><%= notif.message %></p>
          </div>

          <div class="actions">
            <% if notif.status == 'pending' && notif.target.present? %>
              <%= link_to update_request_wager_path(notif.target.try(:wager), member_id: notif.target_id, type: "accept", notif_id: notif.id), method: :put, class: "btn table-link acceptBtn red-btn-small", data: { confirm: 'Are you sure you want to accept?' } do %>
                <i class="fa fa-check" aria-hidden="true"></i>
              <% end %>
              <%= link_to update_request_wager_path(notif.target.wager, member_id: notif.target_id, type: "reject", notif_id: notif.id), method: :put,class: "btn table-link rejectBtn red-btn-small", data: { confirm: 'Are you sure you want to reject?' } do %>
                <i class="fa fa-times" aria-hidden="true"></i>
              <% end %>
            <% end %>
            <%= link_to get_notification_url(notif) + "#" + notif.notify_type.downcase + "Notif", class: "btn red-btn-small" do %>
                <i class="fa fa-eye" aria-hidden="true"></i>
            <% end %>
          </div>


        </div>


      <% end %>

    <% end %>

  </div>

【问题讨论】:

  • 您的代码似乎按预期工作,您可以提供由 rails 构建的 html 吗?

标签: javascript jquery html twitter-bootstrap bootstrap-4


【解决方案1】:

您的意思是您生成的 HTML 将如下所示...所有 div 包含与“media n-media notif-popup-container notif-display”相同的多个类。点击事件必须使用任何一个类作为“.notif-popup-container”或“.notif-display”,此代码将正常工作。

   <div class="media n-media notif-popup-container notif-display" data-id="1">
        Content 1
    </div>
    <div class="media n-media notif-popup-container notif-display" data-id="2">
        Content 2
    </div>
    <div class="media n-media notif-popup-container notif-display" data-id="3">
        Content 3
    </div>

示例代码sn-ps as

    <script>

        $(function () {
            $('body').on("click", ".notif-popup-container", function () {
               console.log($(this).data("id"));
            });
        });

    </script>

或者也可以这样……

    <script>
    $(function () {
        $('body').on("click", ".notif-display", function () {
            console.log($(this).data("id"));
        });
     });
    </script>

我希望这一切都会好起来的……加油

【讨论】:

  • 嗨 Azizur,实际上 div 看起来几乎和你说的一模一样,除了 data-id 属性没有出现在 chrome 开发工具中。奇怪的是,当我将 display:none 更改为 display:show 时,data-id 属性将作为 div 的一部分可见。它还显示在页面上任何其他未隐藏的 div 元素上(通过测试发现)。也许这会提供一些线索?我在整个 div 上显示:none 的原因是因为在初始化弹出框时将其提供给弹出框标题和内容选项。查看编辑,谢谢!
【解决方案2】:

Event Delegation

事件委托是一种编程模式,它允许我们通过绑定(又名注册)事件到所有目标标签共同作为祖先的单个标签。我将其称为“共同祖先”——windowdocumentbody 始终有效,但在大多数情况下不是最佳选择。

除了调用堆栈中只有一个事件处理程序之外,任何在页面加载后动态添加到页面的目标标签都会对已注册的触发事件做出反应——无法将事件绑定到页面加载后创建的标签。

jQuery .on() 方法在提供实际选择器时委托事件:

$('.btn-group').on('click',...

.btn-group 是绑定到事件的标签(共同祖先),并且在其任何后代标签(目标标签)上触发时将监听这些事件。有很多方法可以在处理程序中引用.btn-group

$('.btn-group')

this                   // Used with plain JavaScript properties and methods
$(this)[0]             // As above
$(this).get()          // As above
event.currentTarget    // As above*
$(this)                // Used with jQuery properties and methods
$(event.currentTarget) // As above*

*event.currentTarget 将始终引用绑定到事件的标签,但this 并非总是如此。如果将名为event.data 的第二个参数定义为选择器,则this 将引用event.data

$('.btn-group').on('click', '.btn-modal', openModal);

$(.btn-modal) 现在也是 $(this),而不是 $('.btn-group')。被点击的$('.btn-group') 的任何后代标签都会触发点击事件,从而调用处理函数openModal()。处理程序将确定哪个标签启动行为或被忽略。点击时触发的标签可以被以下引用:

事件来源 - 用户点击、更改、悬停等标签。

event.target    // Used with plain JavaScript properties and methods
this            // As above if `event.data` is defined
$(this)[0]      // As above
$(this).get()   // As above
$(event.target) // Used with jQuery properties and methods
$(this)         // As above if `event.data` is defined

event.target 将始终引用用户与之交互(例如点击)的标签。


演示

注意:详情在demo中注释

/*
If there are multiple tags to target

  ex. 3 button.btn-modal
  
Determine the closest parent tag that the target tags have in common. 

  ex. fieldset.btn-group
  
Delegate the event to the "common ancestor". Add the handler function 
(ie `openModal()`) without the parenthesis.

  ex. $('.btn-group').on('click', openModal);
  
*/
$('.btn-group').on('click', openModal);

/*
Pass thru the event object
Use the event object property .target to determine which tag the user clicked. 
Make it into a jQuery object by wrapping it into $(...)

  ex. let clicked = $(event.target);
  
If the clicked tag has a .btn-modal class...

  ex. if (clicked.hasClass('btn-modal')) {...
  
...get the clicked tag data-open value...

  ex. let ID = clicked.data('open');
  
...Finally, use previous value, ID, as a reference to a modal using the Bootstrap 
method .modal() to open said modal.*

  ex. $('#'+ID).modal();
  
*/
function openModal(event) {
  let clicked = $(event.target);
  if (clicked.hasClass('btn-modal')) {
    let ID = clicked.data('open');
    $('#' + ID).modal();
  }
  return false;
}

/*
*Note: Patterns involving .btn-modal classes and data-open attributes 
are of my own design
*/
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" 
rel="stylesheet">
</head>

<body>
  <main class="container">
    <section class='row'>

      <fieldset class='btn-group btn-group-lg mx-auto mt-5'>
        <button class="btn btn-primary btn-modal" data-open="noticeA" type="button">
          Notice A
        </button>
        <button class="btn btn-warning btn-modal" data-open="noticeB" type="button">
          Notice B
        </button>
        <button class="btn btn-danger btn-modal" data-open="noticeC" type="button">
          Notice C
        </button>
      </fieldset>

      <dialog id="noticeA" class="modal fade">
        <div class="modal-dialog modal-dialog-centered modal-lg">
          <div class="modal-content">
            <header class="modal-header bg-primary">
              <h4 class="modal-title text-white">Notice A</h4>
              <button class="close" type="button" data-dismiss="modal">
                &times;
              </button>
            </header>
            <article class="modal-body">
              <p class='display-1 text-center'>HEY!</p>
            </article>
            <footer class="modal-footer">
     <button class="close btn btn-primary p-3" type="button" data-dismiss="modal">
       Close
     </button>
            </footer>
          </div>
        </div>
      </dialog>

      <dialog id="noticeB" class="modal fade">
        <div class="modal-dialog modal-dialog-centered modal-sm">
          <div class="modal-content">
            <header class="modal-header bg-warning">
              <h4 class="modal-title">Notice B</h4>
              <button class="close" type="button" data-dismiss="modal">
                &times;
              </button>
            </header>
            <article class="modal-body">
              <p class='display-1 text-center'>HEY!</p>
            </article>
            <footer class="modal-footer">
     <button class="close btn btn-warning p-3" type="button" data-dismiss="modal">
       Close
     </button>
            </footer>
          </div>
        </div>
      </dialog>

      <dialog id="noticeC" class="modal fade">
        <div class="modal-dialog modal-dialog-centered modal-lx">
          <div class="modal-content">
            <header class="modal-header bg-danger">
              <h4 class="modal-title text-white">Notice C</h4>
              <button class="close" type="button" data-dismiss="modal">
                &times;
              </button>
            </header>
            <article class="modal-body">
              <p class='display-1 text-center'>HEY!</p>
            </article>
            <footer class="modal-footer">
     <button class="close btn btn-danger p-3" type="button" data-dismiss="modal">
       Close
     </button>
            </footer>
          </div>
        </div>
      </dialog>

    </section>
  </main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js">
  </script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0
/umd/popper.min.js">
  </script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js">
  </script>
</body>

</html>

【讨论】:

  • 您好,zer00ne,您的回答非常有用,但在我的特殊情况下,有一些不同的细节对于弥合差距很重要。 1. 我的 .notif-popup-container 元素的共同祖先,在页面加载时在 DOM 上可见,实际上是“body”,所以这是唯一可以在委托方面起作用的元素。 2. event.target 有点太具体了,它可能会根据用户在该 div 中单击的位置获得实际所需 .notif-popup-container div 的特定

    。 3. data-id 属性仍然没有出现。它可能与 :hidden 属性有关,看@edits!
  • 嗨@KevinSun 如果你想要一个明确的答案,然后发布 HTML。关于第 2 点。event.target 正是您所需要的。当您委托事件时,必须使用条件编写处理程序(例如if/else if/elseswitch()、三元表达式等)。如果操作正确,只有您想要的标签才会对注册的事件做出反应。 body 的事件附件有一个为测试而设计的处理程序……但它没有用,因为它给出了误报。我无法详细说明,因为我仍然需要 HTML 来确定地评估问题。
  • 嗨@zer00ne,我已经发布了html。通过仅使用确实显示的“id”属性,我已经解决了未显示在元素上的 data-id 属性。但我仍然很好奇为什么 data-id 没有出现!谢谢。
猜你喜欢
  • 2020-01-21
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多