Blazor WASM:iframe嵌入pdfjs产生多实例未销毁,如何跳转前销毁?
解决Blazor WASM中iframe嵌入PDF.js的内存泄漏问题
核心问题原因
每次进入页面时iframe会加载新的PDF.js实例,但离开页面时iframe仅被隐藏而非销毁,PDF.js的内存资源也未主动释放,导致实例持续累积占用内存。
解决步骤
1. 利用Blazor组件生命周期清理iframe
Blazor组件实现IDisposable接口后,可在组件销毁(离开页面)时执行清理逻辑:
- 给iframe添加
@ref引用,方便代码中获取元素 - 在
Dispose方法中移除iframe并清空其src,断开资源连接
代码示例:
@implements IDisposable <iframe @ref="_pdfIframe" id="pdfViewer" src="_content/Somiso.Net.PdfViewer/lib/pdfjs/web/viewer.html" style="@Style"></iframe> @code { private ElementReference _pdfIframe; private IJSObjectReference? _jsHelper; protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { _jsHelper = await JS.InvokeAsync<IJSObjectReference>("import", "./pdf-viewer-cleanup.js"); } } public void Dispose() { _jsHelper?.InvokeVoidAsync("cleanupViewer", _pdfIframe); _jsHelper?.DisposeAsync(); } }
对应的pdf-viewer-cleanup.js代码:
export function cleanupViewer(iframeElement) { // 先清空src断开PDF.js连接 iframeElement.src = 'about:blank'; // 从DOM中移除iframe iframeElement.remove(); }
2. 主动通知PDF.js销毁内部实例
仅移除iframe不够,需主动触发PDF.js的资源销毁逻辑,通过postMessage实现跨iframe通信:
- 第一步:修改PDF.js的
viewer.html,添加消息监听
在viewer.html的<script>末尾追加:
window.addEventListener('message', (event) => { if (event.data === 'destroy-pdf') { if (typeof PDFViewerApplication !== 'undefined') { // 调用PDF.js内置销毁方法,强制清理内存 PDFViewerApplication.destroy({ cleanupMemory: true }); } } });
- 第二步:更新JS清理方法,先发送销毁指令
修改pdf-viewer-cleanup.js:
export function cleanupViewer(iframeElement) { // 先通知PDF.js销毁自身实例 iframeElement.contentWindow.postMessage('destroy-pdf', '*'); // 延迟执行DOM移除,确保销毁逻辑完成 setTimeout(() => { iframeElement.src = 'about:blank'; iframeElement.remove(); }, 100); }
3. 验证效果
完成修改后,每次离开PDF预览页面时:
- 会先触发PDF.js销毁内部的文档、渲染资源
- 再彻底移除iframe元素,清空DOM关联的内存占用
可通过Chrome开发者工具的Memory面板拍摄前后内存快照,确认PDF.js实例不再累积。
内容的提问来源于stack exchange,提问作者Frank Mehlhop
相关产品推荐
相关产品推荐

