Blazor如何实时持续获取当前浏览器窗口宽度并响应resize事件
Blazor 窗口宽度实时监听实现方案
核心实现逻辑为:将原本单次拉取宽度的模式,改为「JS监听resize事件 → 主动通知Blazor侧更新宽度值 → 触发组件重渲染」的推送模式,首先需要修正你现有代码的问题:你当前的JS代码中addEventListener返回值是事件监听ID,不是窗口宽度,所以根本无法拿到正确的宽度值。
分步实现代码
步骤1:调整JS代码
新增节流逻辑避免resize事件触发过于频繁,同时增加主动通知Blazor的回调逻辑:
let dotNetRef; // 初始化监听,接收Blazor侧传入的DotNet引用 export function initResizeListener(dotNetReference) { dotNetRef = dotNetReference; // 首次加载先返回当前宽度 sendWidthUpdate(); // 注册resize监听,200ms节流可自行调整 let resizeTimer; window.addEventListener("resize", () => { clearTimeout(resizeTimer); resizeTimer = setTimeout(sendWidthUpdate, 200); }); } // 向Blazor侧推送最新宽度 function sendWidthUpdate() { dotNetRef?.invokeMethodAsync('UpdateWindowWidth', window.innerWidth); }
步骤2:调整UtilityService代码
封装宽度变化事件供组件订阅:
public class UtilityService { private IJSObjectReference _module; // 宽度变化通知事件,组件可订阅该事件获取更新 public event Action<double> OnWindowWidthChanged; // 你原本的GetModule逻辑保持不变即可 private async Task<IJSObjectReference> GetModule() { return _module ??= await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./你的JS文件路径.js"); } // 初始化监听方法 public async Task InitResizeListener(DotNetObjectReference<UtilityService> dotNetRef) { var module = await GetModule(); await module.InvokeVoidAsync("initResizeListener", dotNetRef); } // 供JS侧调用的回调方法 [JSInvokable] public void UpdateWindowWidth(double width) { OnWindowWidthChanged?.Invoke(width); } }
需要先在Program.cs中注册服务:
builder.Services.AddScoped<UtilityService>();
步骤3:调整Razor组件代码
订阅宽度变化事件,收到更新后触发重渲染:
@inject UtilityService utilityService @implements IAsyncDisposable @* 你原本的宽度判断分支逻辑保持不变 *@ @if (width < 768) { // 小屏布局代码 } else { // 大屏布局代码 } @code { private double width; private DotNetObjectReference<UtilityService> _dotNetRef; protected override async Task OnInitializedAsync() { _dotNetRef = DotNetObjectReference.Create(utilityService); // 订阅宽度变化事件 utilityService.OnWindowWidthChanged += UpdateWidth; // 初始化监听 await utilityService.InitResizeListener(_dotNetRef); } private void UpdateWidth(double newWidth) { width = newWidth; // 通知组件状态更新,触发重渲染 StateHasChanged(); } // 销毁时释放资源避免内存泄漏 public async ValueTask DisposeAsync() { utilityService.OnWindowWidthChanged -= UpdateWidth; _dotNetRef?.Dispose(); } }
注意事项
- 若只有单个组件需要监听宽度变化,也可以直接在组件内创建DotNet引用,不需要通过UtilityService中转,逻辑完全一致
- JS中的节流时长可根据业务需求调整,避免resize事件触发过于频繁导致性能损耗
内容的提问来源于stack exchange,提问作者Franco
相关产品推荐
相关产品推荐

