【问题标题】:jQuery multi-level accordion menujQuery多级手风琴菜单
【发布时间】:2015-07-22 13:39:26
【问题描述】:

我在网上找到了一些手风琴菜单,但要么它们不支持多层次,要么代码非常神秘,我不想使用它。所以我决定,我要编写自己的手风琴菜单,它支持任意数量的子菜单。

这是我目前所拥有的:

$(document).ready(function() {

  // at the beginning only the top menu items are visible
  $('.multi-level-accordion-menu > li ul').slideUp(0);
  console.log('all elements slid up');

  // when a menu item which is not active is clicked, show the next lower level
  // when a menu item which is active is clicked, hide all its sub menu items
  $('.multi-level-accordion-menu li').click(function() {
    var menu_item = $(this);

    if (is_active(menu_item)) {
      console.log('active menu item clicked');
      close_menu_item(menu_item);

    } else {
      console.log('inactive menu item clicked');
      open_menu_item(menu_item);
    }
  });

  console.log('READY!');
});

function open_menu_item(menu_item) {
  menu_item.children('ul').slideDown(500);
  menu_item.addClass('active-menu-item');
}

function close_menu_item(menu_item) {
  console.log('1x');

  menu_item.find('ul').each(function(index, elem) {
    $(elem).slideUp();
    return false;
  });

  menu_item.removeClass('active-menu-item');
}

function is_active(menu_item) {
  return menu_item.hasClass('active-menu-item');
}
.multi-level-accordion-menu * {
  margin: 0px;
  padding: 0px;
}
.multi-level-accordion-menu {
  list-style: none;
  max-width: 200px;
}
.multi-level-accordion-menu ul {
  list-style: none;
}
.multi-level-accordion-menu li {
  border-color: #EEEEEE;
  border-width: 1px;
  border-style: solid;
  background-color: #303030;
  margin: 2px;
  padding: 2px;
  line-height: 30px;
  font-size: 16px;
}
.multi-level-accordion-menu {
  color: #DDDDDD;
}
body {
  background-color: #202020;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<body>
  <div>
    <ul class='multi-level-accordion-menu'>
      <li>Item 1
        <ul>
          <li>Item 1.1
            <ul>
              <li>Item 1.1.1</li>
              <li>Item 1.1.2</li>
              <li>Item 1.1.3</li>
              <li>Item 1.1.4</li>
            </ul>
          </li>
          <li>Item 1.2</li>
          <li>Item 1.3</li>
          <li>Item 1.4</li>
          <li>Item 1.5</li>
          <li>Item 1.6</li>
        </ul>
      </li>
      <li>Item 2</li>
      <li>Item 3
        <ul>
          <li>Item 3.1
            <ul>
              <li>Item 3.1.1</li>
              <li>Item 3.1.2</li>
              <li>Item 3.1.3</li>
              <li>Item 3.1.4</li>
            </ul>
          </li>
          <li>Item 3.2</li>
          <li>Item 3.3</li>
          <li>Item 3.4</li>
          <li>Item 3.5</li>
          <li>Item 3.6</li>
        </ul>
      </li>
      <li>Item 4</li>
      <li>Item 5</li>
      <li>Item 6</li>
      <li>Item 7</li>
    </ul>
  </div>
</body>

http://jsfiddle.net/Zelphir/1fp03oyq/1/

点击顶级菜单项可以工作,但是当我点击Item 1 然后Item 1.1 时,很明显,较低的级别还不能工作。子菜单打开,但不知何故同时顶层再次关闭。

如何实现以下行为:

  1. 单击“非活动”菜单项使其子菜单项可见
  2. 单击“活动”菜单项会隐藏其子菜单项及其子菜单项
  3. 一开始所有项目都处于“非活动状态”

【问题讨论】:

  • 看看事件冒泡。这似乎是一个经典案例。
  • 已经这样做了,这就是为什么您可以在代码中看到 return false; 的原因 - 没有帮助,或者它位于代码中的错误位置。你能提供一个有用的答案吗?
  • 下次把代码放到问题里,jsFiddle已经不够用了……
  • 啊,好吧,SO 编辑告诉我,但在某些时候,气泡通知消失了,我想“好吧,似乎只需要防止一个衬里。让帖子保持苗条。”跨度>

标签: jquery html menu accordion jquery-ui-accordion


【解决方案1】:

这应该适合你。

$('.multi-level-accordion-menu').click(function(e){
    var menu_item = $(e.target);

    if(is_active(menu_item)) {
        console.log('active menu item clicked');
        close_menu_item(menu_item);

    } else {
        console.log('inactive menu item clicked');
        open_menu_item(menu_item);          
    }
});

function close_menu_item(menu_item) {
    console.log('1x');

    menu_item.find('ul').each(function() {
        $(this).slideUp().find('li').removeClass('active-menu-item');
    });

    menu_item.removeClass('active-menu-item');
}

或者一个/两个班轮

function close_menu_item(menu_item) {
    console.log('1x');  

    menu_item.removeClass('active-menu-item').find('ul').slideUp().
    find('li').removeClass('active-menu-item');
}

回应您的评论:

在这种情况下,冒泡是导致“点击”方法在最外层容器 (.multi-level-accordion-menu) 上触发的原因。

当你点击一个子元素时,它被存储在一个'event'对象的'target'属性中,并且点击事件冒泡直到它碰到你在jQuery选择器中定义的最外层容器(再次- .multi-level-accordion-menu)。

最外面的容器坐在那里监听“点击”事件,所以当这个事件冒泡到它上面时,它会进入函数。

然后,您将选择触发它的目标元素(存储在“事件”对象的“目标”属性中)并在其上执行任何您想要的操作。 由于您现在在函数内部并且其中没有事件侦听器,因此不会触发更多事件,因此不会进一步冒泡。函数完成,不再触发“点击”事件,因为事件已经冒泡到顶部。

在您的原始代码中,您正在侦听所有“li”元素上的点击事件,因此当您点击“li”元素时,它会立即触发点击侦听器,然后运行您的函数。 然后,当函数完成时,事件会冒泡到祖先“li”元素,再次触发侦听器并再次运行该方法。以此类推。

希望这能澄清一点!

【讨论】:

  • 这对我有用,谢谢!我不明白的是为什么事件没有冒泡并且外部 LI 元素也没有受到影响。你能解释一下吗?
  • 哇,额外的解释真的很有帮助,谢谢!所以这意味着我永远不需要为每个我想在点击时做出反应的项目编写一个 .click() ,而是我可以上一层(如果有的话)并检查事件的目标成员.我认为这会简化一些代码。
猜你喜欢
  • 2011-05-10
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2013-02-03
  • 1970-01-01
  • 2023-03-04
  • 1970-01-01
相关资源
最近更新 更多