动画结束时执行函数,首次调用后失效问题求助
Fixing Animation End Callback Failure on Repeated Div Toggle
我来帮你排查这个问题并给出优化方案~
首先说下问题根源:你用了jQuery的.one()方法绑定动画结束事件,这个方法的特性是事件只会被触发一次,第一次隐藏动画完成后,这个事件绑定就自动移除了。所以后续再点击隐藏时,动画虽然会执行,但不会触发display: none的回调,这就是多次点击后失效的原因。
下面给你几个可行的解决思路:
方案一:使用命名空间事件绑定(推荐)
把.one()改成带命名空间的.on(),每次触发隐藏前先解绑旧的事件,避免重复绑定,确保每次动画结束都能触发回调:
$('#nav-bar-util').on('click', '.util-box', function() { // 用const声明变量,避免全局污染 const $this = $($(this).data('link')); if ($this.is(':hidden')) { $this .css('display', 'block') .removeClass('window-close') .addClass('window-active'); } else { // 先解绑同名空间的动画结束事件,防止重复触发 $this.off('animationend.toggleWindow') .removeClass('window-active') .addClass('window-close') .on('animationend.toggleWindow', function() { $this.css('display', 'none'); // 执行完回调后解绑事件,避免内存泄漏 $(this).off('animationend.toggleWindow'); }); } });
这个方案的优势是完全依赖动画的实际结束事件,不会受动画时长变化的影响,可靠性最高。
方案二:定时器配合动画时长
如果不想用事件绑定,可以根据你的window-close动画时长,用setTimeout来触发隐藏操作。假设你的动画时长是300ms,代码如下:
$('#nav-bar-util').on('click', '.util-box', function() { const $this = $($(this).data('link')); if ($this.is(':hidden')) { $this .css('display', 'block') .removeClass('window-close') .addClass('window-active'); } else { $this .removeClass('window-active') .addClass('window-close'); // 定时器时间要和CSS动画时长严格匹配 setTimeout(() => { $this.css('display', 'none').removeClass('window-close'); }, 300); } });
这个方案更简单,但缺点是如果后续修改了动画时长,必须同步修改定时器的时间,否则会出现显示异常。
额外优化点
- 原代码中
$this没有声明变量,会变成全局变量,建议用const或let声明,避免意外的变量污染。 - 显示元素时,可以先确保移除
window-close类,防止两个动画类同时存在导致的样式冲突。
内容的提问来源于stack exchange,提问作者Asaf Aviv
相关产品推荐
相关产品推荐

