You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 9手风琴菜单子菜单显示切换高度过渡动画实现需求

嘿,我仔细看了你的Angular 9手风琴菜单代码,功能逻辑是没问题的,但子菜单的动画确实可以优化得更流畅。要实现你想要的高度过渡效果,核心问题在于display: none/block是没法做过渡动画的——浏览器对这个属性的变化是瞬间完成的,不会触发过渡。我们可以用高度+overflow的方式来模拟显示隐藏,同时完全保留你现有的代码结构,只需要修改样式和一点点逻辑,就能达到你参考示例的效果。

具体修改方案

1. 替换子菜单的CSS样式

先把原来控制display的逻辑换成高度过渡的样式,这是动画的核心:

/* 子菜单基础样式:默认折叠,高度为0,隐藏溢出内容 */
.submenu {
  overflow: hidden;
  height: 0;
  /* 自定义过渡时长和曲线,这里用0.3秒的缓动效果,和参考示例一致 */
  transition: height 0.3s ease-in-out;
}

2. 调整TS中的切换逻辑

原来的代码是直接修改style.display,现在改成动态控制高度(两种方案可选,看你想要的精准度):

方案一:简单版(用max-height近似实现)

这种方式代码改动最小,适合菜单内容高度变化不大的场景:

  1. 先给展开状态加一个CSS类:
.submenu.open {
  /* 设置一个足够容纳子菜单内容的max-height,根据你的实际情况调整 */
  max-height: 600px;
}
  1. 修改toggleSubmenu方法,把设置display改成添加/移除类:
toggleSubmenu(event: Event, item: any) {
  event.preventDefault();
  item.expanded = !item.expanded;

  const submenuElement = (event.currentTarget as HTMLElement).nextElementSibling;
  if (!submenuElement) return;

  // 替换原来的display控制,改用类名切换
  if (item.expanded) {
    this.renderer.addClass(submenuElement, 'open');
  } else {
    this.renderer.removeClass(submenuElement, 'open');
  }
}

方案二:精准版(动态计算内容高度)

如果想要和参考示例完全一致的精准动画(根据子菜单实际内容高度过渡),可以用这种方式,不需要额外的CSS类:

toggleSubmenu(event: Event, item: any) {
  event.preventDefault();
  item.expanded = !item.expanded;

  const submenuElement = (event.currentTarget as HTMLElement).nextElementSibling;
  if (!submenuElement) return;

  if (item.expanded) {
    // 展开步骤:先让元素获取真实高度,再从0过渡到该高度
    this.renderer.setStyle(submenuElement, 'height', 'auto');
    const actualHeight = submenuElement.scrollHeight + 'px';
    
    // 重置高度为0,触发浏览器重绘后再设置为真实高度
    this.renderer.setStyle(submenuElement, 'height', '0');
    setTimeout(() => {
      this.renderer.setStyle(submenuElement, 'height', actualHeight);
    }, 0);
  } else {
    // 折叠步骤:先获取当前高度,再过渡到0
    const actualHeight = submenuElement.scrollHeight + 'px';
    this.renderer.setStyle(submenuElement, 'height', actualHeight);
    
    setTimeout(() => {
      this.renderer.setStyle(submenuElement, 'height', '0');
    }, 0);
  }
}

3. 保留现有结构的关键细节

  • 你的菜单数据结构(带children的数组)完全不需要修改,继续用原来的*ngFor遍历渲染即可
  • 点击事件绑定逻辑不变,只是修改了toggleSubmenu内部的样式控制方式
  • 两种方案都不需要引入额外的Angular模块(比如@angular/animations),完全基于原生CSS和少量TS逻辑实现,符合你“尽可能保留现有结构”的需求

这样修改后,点击父菜单时,子菜单就会平滑地展开/折叠,高度从0过渡到内容实际高度,完美匹配你想要的动画效果。

内容的提问来源于stack exchange,提问作者Sergio Mendez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 16:43:03