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近似实现)
这种方式代码改动最小,适合菜单内容高度变化不大的场景:
- 先给展开状态加一个CSS类:
.submenu.open { /* 设置一个足够容纳子菜单内容的max-height,根据你的实际情况调整 */ max-height: 600px; }
- 修改
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
相关产品推荐
相关产品推荐

