Angular中如何监听指定动画的元素状态变化并识别:enter/:leave状态
实现指定动画key的元素状态监听方案
这里以Vue生态的动画场景为例,通过封装全局动画事件管理器+动画钩子上报的方式就能实现你要的订阅式监听效果,具体实现步骤如下:
步骤1:实现全局动画管理单例
创建animationObserver.js文件,实现你需要的on、subscribe接口能力:
class AnimationObserver { constructor() { // 按动画key存储订阅回调列表 this.subscriberMap = new Map() } // 绑定要监听的动画key on(animationKey) { if (!this.subscriberMap.has(animationKey)) { this.subscriberMap.set(animationKey, []) } return { // 注册回调,返回取消订阅的方法 subscribe: (callback) => { this.subscriberMap.get(animationKey).push(callback) return () => { const callbackList = this.subscriberMap.get(animationKey) const idx = callbackList.indexOf(callback) if (idx > -1) callbackList.splice(idx, 1) } } } } // 内部方法:动画触发时上报事件 emit(animationKey, targetEl, animationState) { if (this.subscriberMap.has(animationKey)) { this.subscriberMap.get(animationKey).forEach(cb => { cb({ el: targetEl, state: animationState }) }) } } } // 导出全局单例 export const animations = new AnimationObserver()
步骤2:在动画触发钩子中上报状态
根据你使用的动画实现方式,在对应的动画生命周期钩子中调用emit方法上报状态即可,两种常见场景的处理方式如下:
- 如果你用Vue原生
<Transition>组件实现动画,可以封装一个全局的通用动画组件代替原生组件,自动上报状态:
<script setup> import { animations } from './animationObserver' const props = defineProps(['name']) </script> <template> <Transition :name="name" @enter="(el) => animations.emit(name, el, 'enter')" @leave="(el) => animations.emit(name, el, 'leave')" <!-- 可根据需要扩展动画结束、动画取消等状态的上报 --> @after-enter="(el) => animations.emit(name, el, 'enter-end')" @after-leave="(el) => animations.emit(name, el, 'leave-end')" v-bind="$attrs" > <slot /> </Transition> </template>
后续使用时把原来的<Transition name="fadeInOut">替换为这个封装组件即可。
- 如果你用自定义指令实现
@fadeInOut这类绑定语法,直接在指令对应的元素挂载/卸载、动画触发的钩子中调用animations.emit上报对应状态即可。
调用效果
和你期望的用法完全一致:
import { animations } from './animationObserver' // 监听fadeInOut动画 const unsubscribe = animations.on('fadeInOut').subscribe((info) => { // info.el是当前触发动画的DOM元素,info.state是动画状态(enter/leave等) console.log(`元素${info.el.id}触发了${info.state}动画`) }) // 不需要监听时调用取消订阅,避免内存泄漏 // unsubscribe()
内容的提问来源于stack exchange,提问作者Mahdi Zarei
相关产品推荐
相关产品推荐

