Blazor WebAssembly含URL锚点时本地化功能失效问题
问题描述
将基于HTML、CSS和JS模板开发的网站转为ASP.NET Core(MVC)项目运行正常,但转为Blazor WebAssembly项目后出现异常:通过锚点标签跳转到页面章节后,本地化组件失效,无法切换语言。
相关代码
CultureSelector.razor 组件
@using System.Globalization @inject IJSRuntime JS @inject NavigationManager Navigation <ul class="list-inline s-header__action s-header__action--lb"> <select class="localeSettings" @bind="Culture"> @foreach (var culture in supportedCultures) { <option class="localeSettingsOption" value="@culture">@culture.DisplayName</option> } </select> </ul> @code { private CultureInfo[] supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("it-IT"), new CultureInfo("de-DE"), }; private CultureInfo Culture { get => CultureInfo.CurrentCulture; set { if (CultureInfo.CurrentCulture != value) { var js = (IJSInProcessRuntime)JS; js.InvokeVoid("blazorCulture.set", value.Name); Navigation.NavigateTo(Navigation.Uri, forceLoad: true); } } } }
Program.cs 配置
using myProject; using System.Globalization; using Microsoft.JSInterop; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add<App>("#app"); builder.RootComponents.Add<HeadOutlet>("head::after"); builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); builder.Services.AddLocalization(); var host = builder.Build(); CultureInfo culture; var js = host.Services.GetRequiredService<IJSRuntime>(); var result = await js.InvokeAsync<string>("blazorCulture.get"); if (result != null) { culture = new CultureInfo(result); } else { culture = new CultureInfo("en-US"); await js.InvokeVoidAsync("blazorCulture.set", "en-US"); } CultureInfo.DefaultThreadCurrentCulture = culture; CultureInfo.DefaultThreadCurrentUICulture = culture; await host.RunAsync();
Index.razor 中的锚点元素
<a href="#js__scroll-to-section" class="s-scroll-to-section-v1--bc g-margin-b-15--xs"> <span class="g-font-size-18--xs g-color--white ti-angle-double-down"></span> <p class="text-uppercase g-color--white g-letter-spacing--3 g-margin-b-0--xs">@Loc["Learn More"]</p> </a>
问题细节:原MVC项目中滚动脚本会移除URL中的锚点,但Blazor应用中锚点会保留(如https://localhost:7123/#js__scroll-to-section),此时语言选择下拉菜单无任何响应。
问题原因与解决方法
核心原因
当URL包含锚点时,Navigation.NavigateTo(Navigation.Uri, forceLoad: true)会带着锚点重载页面,导致Blazor初始化时的文化读取逻辑未正确触发,或重载后的页面因锚点存在引发组件状态更新异常,最终导致文化切换失效。
具体修复方案
1. 修正CultureSelector的导航逻辑:移除URL锚点
修改Culture属性的setter,跳转时剔除URL中的锚点部分,确保重载时使用干净的基础URL:
private CultureInfo Culture { get => CultureInfo.CurrentCulture; set { if (CultureInfo.CurrentCulture != value) { var js = (IJSInProcessRuntime)JS; js.InvokeVoid("blazorCulture.set", value.Name); // 移除URL中的锚点,只保留基础路径 var cleanUri = Navigation.Uri.Split('#')[0]; Navigation.NavigateTo(cleanUri, forceLoad: true); } } }
2. 替换原生锚点为Blazor+JS滚动
避免使用原生<a href="#xxx">(会残留锚点在URL),改用Blazor点击事件结合JS实现滚动,并手动移除URL锚点:
修改Index.razor中的元素
<button @onclick="() => ScrollToSection('js__scroll-to-section')" class="s-scroll-to-section-v1--bc g-margin-b-15--xs" style="background: none; border: none; cursor: pointer;"> <span class="g-font-size-18--xs g-color--white ti-angle-double-down"></span> <p class="text-uppercase g-color--white g-letter-spacing--3 g-margin-b-0--xs">@Loc["Learn More"]</p> </button> @code { [Inject] private IJSRuntime JS { get; set; } private async Task ScrollToSection(string sectionId) { // 调用JS实现平滑滚动 await JS.InvokeVoidAsync("scrollToSection", sectionId); // 移除URL中的锚点 await JS.InvokeVoidAsync("history.replaceState", null, "", Navigation.BaseUri); } }
在index.html中添加滚动脚本
<script> function scrollToSection(sectionId) { const element = document.getElementById(sectionId); if (element) { element.scrollIntoView({ behavior: 'smooth' }); } } </script>
3. 确保blazorCulture脚本正常工作
确认你的全局JS脚本(如index.html中)正确实现了localStorage的读写:
<script> window.blazorCulture = { get: () => localStorage.getItem('culture'), set: (culture) => localStorage.setItem('culture', culture) }; </script>
内容的提问来源于stack exchange,提问作者Code4Fun
相关产品推荐
相关产品推荐

