в jQuery события мыши запускают неправильный элемент. Как я могу это исправить?

#javascript #jquery #twitter-bootstrap

Вопрос:

Я работаю над навигационной панелью начальной загрузки на веб-сайте WordPress с этим HTML-кодом — >

 <nav id="menu" class="navbar navbar-expand-md navbar-light bg-faded">
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs4navbar"
            aria-controls="bs4navbar" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <div id="bs4navbar" class="collapse navbar-collapse">
        <ul id="menu-main" class="navbar-nav mr-auto">

            <li id="menu-item-61"
                class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-61 nav-item"><a
                    href="#"
                    class="nav-link">ITEM 61</a></li>

            <li id="menu-item-59"
                class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-59 nav-item"><a
                    href="#"
                    class="nav-link">ITEM 59</a></li>

            <li id="menu-item-56"
                class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-56 nav-item dropdown">
                <a href="#"
                   class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 56</a>
                <div class="dropdown-menu">
                    <a href="#"
                       class=" dropdown-item">ITEM 56 - A</a><a
                        href="#"
                        class=" dropdown-item">ITEM 56 - B</a></div>
            </li>
            <li id="menu-item-48"
                class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-48 nav-item dropdown">
                <a href="#"
                   class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 48</a>
                <div class="dropdown-menu">
                    <a href="#"
                       class=" dropdown-item">ITEM 48 - A</a><a
                        href="#"
                        class=" dropdown-item">ITEM 48 - B</a><a
                        href="#"
                        class=" dropdown-item">ITEM 48 - C</a><a
                        href="#"
                        class=" dropdown-item">ITEM 48 - D</a></div>
            </li>

            <li id="menu-item-53"
                class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-53 nav-item dropdown">
                <a href="#"
                   class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 53</a>
                <div class="dropdown-menu" style="display: none;">
                    <a href="#"
                       class=" dropdown-item">ITEM 53 - A</a><a
                        href="#"
                        class=" dropdown-item">ITEM 53 - B</a></div>
            </li>

        </ul>
    </div>
</nav>

 

Пункты 56, 48 и 53 имеют .dropdown-menu , в основном, когда я нажимаю на один из них, я ожидаю увидеть подменю; его собственный bootstrap.js сценарий не работает (я не знаю причины).

Чтобы исправить это, я могу вызвать событие мыши с помощью этого кода ->

 <script>

            $(function ($) {

                $nav = $('nav#menu');

                $('.dropdown', $nav).each(function () {

                    console.log('.dropdown ->');
                    console.log($(this));

                    $subMenu = $('.dropdown-menu', $(this));

                    console.log('$subMenu ->');
                    console.log($subMenu);

                    $(this).mouseenter(function () {

                        console.log('mouseenter ->');
                        console.log($(this));

                        $subMenu.show();

                        console.log('$subMenu ->');
                        console.log($subMenu);

                    }).mouseleave(function () {

                        console.log('mouseleave ->');
                        console.log($(this));

                        $subMenu.hide();

                        console.log('$subMenu ->');
                        console.log($subMenu);
                    });

                });

            });

        </script>
 
 $(function($) {

  $nav = $('nav#menu');

  $('.dropdown', $nav).each(function() {

    console.log('.dropdown ->');
    console.log($(this));

    $subMenu = $('.dropdown-menu', $(this));

    console.log('$subMenu ->');
    console.log($subMenu);

    $(this).mouseenter(function() {

      console.log('mouseenter ->');
      console.log($(this));

      $subMenu.show();

      console.log('$subMenu ->');
      console.log($subMenu);

    }).mouseleave(function() {

      console.log('mouseleave ->');
      console.log($(this));

      $subMenu.hide();

      console.log('$subMenu ->');
      console.log($subMenu);
    });

  });

}); 
 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="undefined" crossorigin="anonymous">

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<nav id="menu" class="navbar navbar-expand-md navbar-light bg-faded">
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#bs4navbar" aria-controls="bs4navbar" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
  <div id="bs4navbar" class="collapse navbar-collapse">
    <ul id="menu-main" class="navbar-nav mr-auto">

      <li id="menu-item-61" class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-61 nav-item"><a href="#" class="nav-link">ITEM 61</a></li>

      <li id="menu-item-59" class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-59 nav-item"><a href="#" class="nav-link">ITEM 59</a></li>

      <li id="menu-item-56" class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-56 nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 56</a>
        <div class="dropdown-menu">
          <a href="#" class=" dropdown-item">ITEM 56 - A</a><a href="#" class=" dropdown-item">ITEM 56 - B</a></div>
      </li>
      <li id="menu-item-48" class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-48 nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 48</a>
        <div class="dropdown-menu">
          <a href="#" class=" dropdown-item">ITEM 48 - A</a><a href="#" class=" dropdown-item">ITEM 48 - B</a><a href="#" class=" dropdown-item">ITEM 48 - C</a><a href="#" class=" dropdown-item">ITEM 48 - D</a></div>
      </li>

      <li id="menu-item-53" class="menu-item menu-item-type-taxonomy menu-item-object-product_cat menu-item-has-children menu-item-53 nav-item dropdown">
        <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">ITEM 53</a>
        <div class="dropdown-menu" style="display: none;">
          <a href="#" class=" dropdown-item">ITEM 53 - A</a><a href="#" class=" dropdown-item">ITEM 53 - B</a></div>
      </li>

    </ul>
  </div>
</nav> 

(Я оставил console.log() его в целях отладки).

Я ожидал увидеть подменю, когда просто наведу курсор мыши на соответствующие области.

(Неправильный) результат заключается в том, что когда я перемещаю мышь в любом из этих 3 элементов, он показывает последний .dropdown-menu в списке.

Консоль показывает правильный элемент .each() , но при запуске отображается только последний .dropdown-menu элемент в списке.

Я не могу понять, как такое может быть возможно.

Кто-нибудь может объяснить, что происходит? и как я могу это исправить?

Комментарии:

1. не используйте это для события

2. Что я должен использовать? @abhinavxeon

3. Ваша проблема связана с закрытиями JavaScript. Вы ссылаетесь this в цикле — к моменту вызова этих функций this это ссылка на последний элемент в цикле. Вместо этого вам нужно сохранить ссылку this и использовать ее в функциях. По соглашению, вы обычно увидите что-то вроде var that = this , и вы можете использовать that внутри своих вложенных функций.

Ответ №1:

Главное, что вам не хватает var при объявлении переменных, поэтому вы создаете глобальные значения.

Я немного привел в порядок ваш код, вот так:

 $(function ($) {
    var $nav = $('nav#menu');

    $nav.find('.dropdown').each(function () {
        var $dropdown = $(this);

        $(this).mouseenter(function () {
            var $subMenu = $dropdown.find('.dropdown-menu');
            $subMenu.show();
        }).mouseleave(function () {
            var $subMenu = $dropdown.find('.dropdown-menu');
            $subMenu.hide();
        });
    });
});
 

Ответ №2:

Что касается комментария, я переместился $subMenu внутрь функции события, и она работает.

Спасибо skyline3000

 <script>

            $(function ($) {

                $nav = $('nav#menu');

                $('.dropdown', $nav).each(function () {

                    $(this).mouseenter(function () {

                        $subMenu = $('.dropdown-menu', $(this));
                        $subMenu.show();

                    }).mouseleave(function () {

                        $subMenu = $('.dropdown-menu', $(this));
                        $subMenu.hide();

                    });

                });

            });

        </script>