我正在使用Blazor技术进行项目。有时我需要使用一些JS代码,并且需要在每个页面中包含不同的js文件,并且据我所知,唯一的方法是使用JS函数和Blazor JS调用添加它。所以我所做的是: 在_Host.razor
中function addScriptFile(fileName){
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", file);
document.getElementById(divName).appendChild(script);
}
然后在每个页面(组件)中
@inject IJSRuntime Js;
@functions{
protected override async void OnAfterRender()
{
await Js.InvokeAsync<object>("addScriptFile","~/js/myFile.js");
}
}
它工作正常,但是如果重新加载页面会发生问题。引发错误 System.InvalidOperationException:当前无法发出JavaScript互操作调用。这是因为组件正在预渲染,并且页面尚未加载到浏览器中,或者因为电路当前已断开连接。组件必须将所有JavaScript互操作调用包装在条件逻辑中,以确保在预渲染期间或客户端断开连接时不尝试这些互操作调用。
我从此错误中了解到,我试图在渲染完成之前调用一些javascript代码。因此,我使用IComponentContext来确保服务器已连接。 在解决此问题的过程中,我创建了一个没有任何JS文件的新Blazor项目,但在重新加载页面时会抛出相同的错误
我试图做到这一点:
@inject IComponentContext ComponentContext
@functions{
protected override void OnAfterRender()
{
if(ComponentContext.IsConnected)
{
//adding scripts
}
}
}
如何使JS以合适的方式与Blazor一起使用? 以及如何解决该错误?
答案 0 :(得分:2)
在您的代码示例中,有两个问题。
@inject IJSRuntime Js;
@functions {
protected override async void OnAfterRender()
{
await Js.InvokeAsync<object>("addScriptFile","~/js/myFile.js");
}
}
首先,您应该使用code
而不是functions
。 Code
特定于Blazor组件,functions
用于Razor Pages和MVC。
第二,永远不要在Blazor中使用async void
,该规则的例外是在事件处理程序中运行异步代码。有关更多信息,请参见this article。
第三,在脚本位置的开头有~
字符。该角色不适用于Blazor(我认为还是毫无意义的),仅对MVC和Razor Pages有效。如果要从应用程序的根目录加载脚本,则只需使用/
,如果要从相对位置加载脚本,则不要在该位置添加前缀。
话虽如此,我认为您的代码应如下所示。
@inject IJSRuntime Js;
@inject IComponentContext ComponentContext
@code {
protected override async Task OnAfterRenderAsync()
{
if (!ComponentContext.IsConnected)
{
return;
}
await Js.InvokeAsync<object>("addScriptFile","/js/myFile.js");
}
}