如何移除addEventListener和requestAnimationFrame相关性能消耗进程
解决方案
核心思路是将原本init方法内的局部变量、事件处理函数、动画帧ID都挂载到类的实例属性上,让removeEventListeners方法可以直接访问对应引用,无需担心作用域问题。
修正后的完整代码
export default class Cursor extends Core { init() { // 把原本的局部变量全部挂载为实例属性 this.xmouse = 0 this.ymouse = 0 this.friction = 0.125 this.x = 0 this.y = 0 this.dx = 0 this.dy = 0 this.animationId = null // 事件处理函数绑定为实例方法,保留this指向 this.mouseMoveHandler = (e) => { this.xmouse = e.clientX || e.pageX this.ymouse = e.clientY || e.pageY } this.$el.addEventListener('mousemove', this.mouseMoveHandler) // 动画函数也挂载为实例方法 this.followMouse = () => { // 存储当前动画帧ID,方便后续取消 this.animationId = requestAnimationFrame(this.followMouse) if (!this.x || !this.y) { this.x = this.xmouse this.y = this.ymouse } else { this.dx = (this.xmouse - this.x) * this.friction this.dy = (this.ymouse - this.y) * this.friction if (Math.abs(this.dx) + Math.abs(this.dy) < 0.1) { this.x = this.xmouse this.y = this.ymouse } else { this.x += this.dx this.y += this.dy } } cursor.style.left = `${this.x}px` cursor.style.top = `${this.y}px` } this.followMouse() } removeEventListeners() { // 移除mousemove事件监听 this.$el.removeEventListener('mousemove', this.mouseMoveHandler) // 取消动画帧请求 cancelAnimationFrame(this.animationId) // 可选:清空相关实例属性,释放内存 this.mouseMoveHandler = null this.followMouse = null this.xmouse = null this.ymouse = null } }
关键改动说明
- 原本
init内部的局部变量全部改为实例属性,跨方法访问无需考虑作用域限制,xmouse、ymouse的读写逻辑完全和之前一致,只是加了this.前缀 - 事件处理函数直接作为实例属性存储,添加和移除监听时都传入同一个引用,符合DOM事件移除的规则
- 每次调用
requestAnimationFrame时都把返回的帧ID存在实例上,调用cancelAnimationFrame时传入该ID即可直接终止整个动画循环
内容的提问来源于stack exchange,提问作者Albert de Beer
相关产品推荐
相关产品推荐

