diff --git a/common/changes/@visactor/vrender-animate/fix-event_release_2026-03-02-12-20.json b/common/changes/@visactor/vrender-animate/fix-event_release_2026-03-02-12-20.json new file mode 100644 index 000000000..a62c0afc0 --- /dev/null +++ b/common/changes/@visactor/vrender-animate/fix-event_release_2026-03-02-12-20.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-animate", + "comment": "fix: fix memory leak by properly removing listener", + "type": "none" + } + ], + "packageName": "@visactor/vrender-animate" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/fix-event_release_2026-03-02-12-20.json b/common/changes/@visactor/vrender-components/fix-event_release_2026-03-02-12-20.json new file mode 100644 index 000000000..57c432073 --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-event_release_2026-03-02-12-20.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "fix: fix memory leak by properly removing listener", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/packages/vrender-animate/src/ticker/default-ticker.ts b/packages/vrender-animate/src/ticker/default-ticker.ts index 21908779e..be842f0f2 100644 --- a/packages/vrender-animate/src/ticker/default-ticker.ts +++ b/packages/vrender-animate/src/ticker/default-ticker.ts @@ -70,9 +70,7 @@ export class DefaultTicker extends EventEmitter implements ITicker { init(): void { this.interval = 16; this.status = STATUS.INITIAL; - application.global.hooks.onSetEnv.tap('graph-ticker', () => { - this.initHandler(false); - }); + application.global.hooks.onSetEnv.tap('graph-ticker', this._handleGraphTick); if (application.global.env) { this.initHandler(false); } @@ -221,6 +219,8 @@ export class DefaultTicker extends EventEmitter implements ITicker { this.tickerHandler?.release(); this.tickerHandler = null; this.lastFrameTime = -1; + + application.global.hooks.onSetEnv.unTap('graph-ticker', this._handleGraphTick); } protected checkSkip(delta: number): boolean { @@ -280,4 +280,8 @@ export class DefaultTicker extends EventEmitter implements ITicker { this.emit('tick', delta); }; + + protected _handleGraphTick = () => { + this.initHandler(false); + }; } diff --git a/packages/vrender-components/src/scrollbar/scrollbar.ts b/packages/vrender-components/src/scrollbar/scrollbar.ts index 23eb563a4..af6ad7db0 100644 --- a/packages/vrender-components/src/scrollbar/scrollbar.ts +++ b/packages/vrender-components/src/scrollbar/scrollbar.ts @@ -444,7 +444,7 @@ export class ScrollBar extends AbstractComponent> * 浏览器上的事件必须解绑,防止内存泄漏,场景树上的事件会自动解绑 */ super.release(all); - (vglobal.env === 'browser' ? vglobal : this.stage).addEventListener('touchmove', this._handleTouchMove, { + (vglobal.env === 'browser' ? vglobal : this.stage).removeEventListener('touchmove', this._handleTouchMove, { passive: false }); this._clearDragEvents(); diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 70e1d6efc..396018041 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -1045,6 +1045,10 @@ export class Stage extends Group implements IStage { this.window.release(); this._ticker?.remTimeline(this?.timeline); this._ticker?.removeListener('tick', this.afterTickCb); + if (!this.params.ticker) { + // release stage创建的ticker,避免release外部的ticker + this._ticker?.release(); + } this.renderService.renderTreeRoots = []; }