Blazor WASM中Rive动画返回默认页面后无法重新渲染求助
问题分析
你的核心问题在于Blazor的组件生命周期和JS模块执行逻辑不匹配:
- 组件首次渲染时
firstRender为true,会导入并执行JS模块顶层代码;但返回页面时组件会重新创建,firstRender为false,不会再次导入执行JS模块。 - JS模块顶层直接创建的Rive实例,绑定的是首次渲染的canvas元素;返回页面后生成的是新的canvas元素,旧实例无法关联到新元素,导致动画不显示。
解决方案
步骤1:重构JS模块,封装可复用的初始化/销毁方法
修改Index.razor.js,将Rive实例的创建和销毁封装成函数,避免顶层代码仅执行一次的问题:
let riveInstance = null; // 初始化Rive动画 export function initRive() { // 先销毁旧实例,避免内存泄漏 if (riveInstance) { riveInstance.destroy(); riveInstance = null; } // 获取当前页面的canvas元素并创建新实例 const canvas = document.getElementById('canvas'); if (canvas) { riveInstance = new rive.Rive({ src: 'bear.riv', canvas: canvas, autoplay: true, }); } } // 销毁Rive实例 export function destroyRive() { if (riveInstance) { riveInstance.destroy(); riveInstance = null; } }
步骤2:修改Blazor组件,适配组件生命周期
修改Index.razor,去掉firstRender限制,每次渲染都初始化动画,并在组件销毁时清理实例:
@page "/" @inject IJSRuntime JSRuntime @implements IAsyncDisposable <canvas id="canvas" width="500" height="500"></canvas> @code { private IJSObjectReference? _jsModule; protected override async Task OnAfterRenderAsync(bool firstRender) { // 仅首次加载时导入JS模块 _jsModule ??= await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./Pages/Index.razor.js"); // 每次渲染都执行初始化,确保关联当前canvas await _jsModule.InvokeVoidAsync("initRive"); } // 组件销毁时清理Rive实例,防止内存泄漏 public async ValueTask DisposeAsync() { if (_jsModule is not null) { await _jsModule.InvokeVoidAsync("destroyRive"); await _jsModule.DisposeAsync(); } } }
关键说明
- 移除
firstRender判断后,每次组件渲染(包括返回页面时)都会调用initRive,确保Rive实例绑定到当前页面的新canvas元素。 - 新增
destroyRive方法并在组件销毁时调用,避免残留的Rive实例占用内存。 - JS模块仅在首次渲染时导入一次,后续直接调用模块内的函数,提升性能。
内容的提问来源于stack exchange,提问作者Laftek
相关产品推荐
相关产品推荐

