下拉菜单单击事件监听器根据单击的区域生成不同的目标元素

Dropdown menu click eventListener producing a different target element based on area clicked

我有一个用这个 HTML 实现的 MaterializeCSS 下拉菜单。只有在上部单击下拉项时事件侦听器才起作用。


    <div class="left">
      <span id="notificationTotal" class="new badge red" style="display:none"> 
      </span>
        <a class="dropdown-trigger" href="#!" data-target="notificationsDropdown">
          <i class="material-icons"> message</i>
        </a>
      </div>
      <ul id="notificationsDropdown" class="dropdown-content">
    </ul>

我正在使用以下 Javascript 来使用通知填充菜单。这工作得很好。

    // Reset Notification Dropdown
    notificationsDropdown.innerHTML = '';

    notifications.forEach(notif => {
      const displayTime = moment(notif.date).fromNow();
      let typeIcon = 'sms';
      if (notif.type === 'chat') {
        typeIcon = 'lock';
      }

      notificationsDropdown.innerHTML += `<li class="notification">
      <a style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;font-size:14px" href="#" class="blue-text">
      <span class="js-patientName">
      ${notif.contact.firstName} ${notif.contact.lastName}</span>
      <span class="js-notificationPhone" style="display:none">${
        notif.contact.phone
      }</span>
      <span class="js-patientId" style="display:none">${
        notif.patientId
      }</span>
      <span class="js-patientDOB" style="display:none">${
        notif.contact.birthDate
      }</span>
      <p style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;padding-top: 0;">
        <i style="display: inline-flex; vertical-align:middle" class="tiny material-icons">${typeIcon}</i>
        <span class="black-text" style="font-size:12px">
        ${displayTime}
        </span>
      </p>
      </a></li>`;
    });
    notificationsDropdown.innerHTML += `<li class="divider" class="blue-text"></li><li><a href="/notifications" class="blue-text">See All Notifications</a></li>`;
  }

下拉菜单会被填充,当用户点击特定的下拉菜单 .li 条目时,取决于他们点击的确切位置,它可能有效也可能无效。用户必须单击下拉项的主顶部。

这是从隐藏的 span 元素中提取值的事件侦听器代码。

  document
    .querySelectorAll('#notificationsDropdown', '.li .a .notification')
    .forEach(input =>
      input.addEventListener('click', async e => {
        // console.log('clicked', e.target);

        console.log(e.target.parentNode);

        const name = e.target.children[0].textContent.trim();
        const phone = e.target.children[1].textContent.trim();
        const patientId = e.target.children[2].textContent.trim();
        const birthDate = e.target.children[3].textContent.trim();
        console.log('patientid ', patientId);

        const patient = {
          name,
          patientId,
          phone,
          birthDate
        };

有什么方法可以重写 eventListener 代码来解决这个问题吗?可能不是使用 e.target.children[insert_number_here].textContent 我可以使用 .closest('js-patientId') 或类似的 ?

这就是 HTML 呈现到页面的方式。这是单个通知的示例:

<ul
  id="notificationsDropdown"
  class="dropdown-content"
  tabindex="0"
  style="display: block; width: 177.297px; left: 1648.7px; top: 0px; height: 251px; transform-origin: 100% 0px; opacity: 1; transform: scaleX(1) scaleY(1);"
>
  <li class="notification">
    <a
      style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;font-size:14px"
      href="#"
      class="blue-text"
    >
      <span class="js-patientName">ANDREW TAYLOR</span>
      <span class="js-notificationPhone" style="display:none">
        5555551212
      </span>
      <span class="js-patientId" style="display:none">
        1
      </span>
      <span class="js-patientDOB" style="display:none">
        1960-01-01
      </span>
      <p style="margin-top:0px;margin-bottom:0px;padding-bottom: 0;padding-top: 0;">
        <i
          style="display: inline-flex; vertical-align:middle"
          class="tiny material-icons"
        >
          sms
        </i>
        <span class="black-text" style="font-size:12px">
          2 hours ago
        </span>
      </p>
    </a>
  </li>
  <li class="divider" />
  <li>
    <a href="/notifications" class="blue-text">
      See All Notifications
    </a>
  </li>
</ul>;

对于下拉菜单,处理操作的更好方法是通过 onChange 事件。因此,您可以将 eventHandler 附加到 dropDown 本身的 onChange 上,而不是将 onClick 附加到每个 dropDown 项目上。因此,每当您更改所选值时,都会触发 onChange 事件,您可以轻松获取所选值。

我能够删除每里的。然后调整值分配以使用以下内容:

e.target.parentNode.children[0].textContent.trim();