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

Vue中等待DOM更新完成触发菜单过渡动画的问题咨询

问题根本原因

Vue 的$nextTick仅保证虚拟DOM对应的真实DOM更新已提交,不会等待浏览器完成样式计算、重排重绘的完整渲染流水线。你两次修改menuStyles的操作会被浏览器的渲染优化机制合并,最终相当于直接把--int-menu-height设为0,没有前后状态差,自然不会触发过渡动画,transitionend也不会执行。


可行解决方案

方案1:强制触发浏览器重排(最简单通用)

主动读取DOM的布局属性会强制浏览器立即计算并应用当前已提交的样式变更,不会和后续修改合并:

const comp = this;
const menu = this.$refs.menu;
const menuHeight = this.$refs.menuHeight.clientHeight+'px';

// 将原本为auto的属性设置为菜单实际高度
this.menuStyles = { '--int-menu-height': menuHeight };
// 强制触发重排,让浏览器立即应用上面的样式变更
void menu.offsetHeight;
// 直接设置为0即可触发过渡
this.menuStyles = { '--int-menu-height': 0 };

menu.addEventListener('transitionend', function closeMenu(e) {
    // 建议加属性判断,避免元素上其他过渡属性误触发回调
    if(e.propertyName === 'height' || e.propertyName === '--int-menu-height') {
        comp.isMenuOpen = false;
        menu.removeEventListener('transitionend', closeMenu);
    }
});

方案2:双requestAnimationFrame等待帧刷新

requestAnimationFrame会在浏览器下一帧渲染前执行,嵌套两次即可保证第一次样式变更已经被应用到当前帧:

const comp = this;
const menu = this.$refs.menu;
const menuHeight = this.$refs.menuHeight.clientHeight+'px';

this.menuStyles = { '--int-menu-height': menuHeight };
requestAnimationFrame(() => {
    requestAnimationFrame(() => {
        this.menuStyles = { '--int-menu-height': 0 };
    })
});

// transitionend监听逻辑同上

注意事项

请确保菜单元素的过渡配置已经正确关联自定义属性,示例如下:

.menu {
    height: var(--int-menu-height);
    transition: --int-menu-height 0.3s ease;
    /* 部分低版本浏览器不支持自定义属性过渡,可直接过渡height属性 */
    /* transition: height 0.3s ease; */
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:18:00