Blazor Server:OnInitialized方法触发两次导致动画重复渲染
Blazor Server组件OnInitialized触发两次的解决方案
Blazor Server默认启用预渲染机制:服务器先生成静态HTML发送给浏览器(预渲染阶段),待SignalR连接建立后,组件会再次初始化并接管DOM,因此OnInitialized会执行两次,导致CSS动画等逻辑重复触发。
以下是两种解决思路:
一、禁用预渲染
如果不需要预渲染带来的SEO和初始加载优势,可以直接关闭预渲染,让组件只初始化一次。
1. 全局禁用(Program.cs)
builder.Services.AddServerSideBlazor(options => { // 禁用全局预渲染 options.DisablePrerendering = true; });
2. 单个组件禁用(.NET 8+)
在目标组件中指定渲染模式,关闭预渲染:
@page "/example" @rendermode InteractiveServer(prerender: false) <h3>@title</h3> @code { private string title; protected override void OnInitialized() { title = "Page is initialized"; Console.WriteLine("OnInitialized is called"); base.OnInitialized(); } }
二、检测预渲染状态,控制逻辑执行
若需要保留预渲染,可通过判断当前是否处于预渲染阶段,让动画等逻辑只在连接建立后执行。
方法1:通过IHttpContextAccessor判断
预渲染阶段存在HttpContext,连接建立后该对象为null。
- 先在Program.cs注册服务:
builder.Services.AddHttpContextAccessor();
- 在组件中注入并判断:
@page "/example" @inject IHttpContextAccessor HttpContextAccessor <h3>@title</h3> <!-- 仅在非预渲染阶段显示带动画的元素 --> @if (!IsPrerendering) { <div class="animated-title">@title</div> } @code { private string title; // 判断是否处于预渲染阶段 private bool IsPrerendering => HttpContextAccessor.HttpContext != null; protected override void OnInitialized() { title = "Page is initialized"; if (!IsPrerendering) { Console.WriteLine("OnInitialized (连接建立后) 被调用"); // 这里执行仅需运行一次的逻辑,比如初始化动画相关操作 } else { Console.WriteLine("OnInitialized (预渲染阶段) 被调用"); } base.OnInitialized(); } }
方法2:使用OnAfterRenderAsync
OnAfterRenderAsync在预渲染阶段不会执行,仅在SignalR连接建立、组件完成首次渲染后触发,适合处理动画这类依赖DOM的逻辑:
@page "/example" @inject IJSRuntime JS <h3 @ref="titleElementRef">@title</h3> @code { private string title; private ElementReference titleElementRef; protected override void OnInitialized() { title = "Page is initialized"; Console.WriteLine("OnInitialized is called"); base.OnInitialized(); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { // 仅在连接建立后的首次渲染执行 Console.WriteLine("OnAfterRenderAsync (首次渲染) 被调用"); // 通过JSInterop触发动画,比如添加CSS类 await JS.InvokeVoidAsync("addClass", titleElementRef, "animate-fade-in"); } await base.OnAfterRenderAsync(firstRender); } }
对应的JS代码(可放在wwwroot/js/app.js中):
window.addClass = (element, className) => { element.classList.add(className); };
内容的提问来源于stack exchange,提问作者yahya
相关产品推荐
相关产品推荐

