为什么Blazor应用程序在任何页面重新加载时均显示错误

时间:2019-07-31 23:23:25

标签: c# blazor

我正在使用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一起使用? 以及如何解决该错误?

1 个答案:

答案 0 :(得分:2)

在您的代码示例中,有两个问题。

@inject IJSRuntime Js;

@functions {
    protected override async void OnAfterRender()
    {
        await Js.InvokeAsync<object>("addScriptFile","~/js/myFile.js");
    }
}

首先,您应该使用code而不是functionsCode特定于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");
    }
}