【问题标题】:Calling javascript from Blazor results in error从 Blazor 调用 javascript 会导致错误
【发布时间】:2020-05-29 05:37:40
【问题描述】:

我有一个基于 .NET Core 3.1 构建的 Blazor 应用,我需要能够访问 USB 端口资源。我不断收到错误:

此时无法发出 JavaScript 互操作调用。这是 因为组件是静态渲染的。预渲染时 启用后,JavaScript 互操作调用只能在 OnAfterRenderAsync 生命周期方法。

我有一个非常简单的 Blazor 组件,其中包含 Blazor.Extensions.WebUSB 库

public partial class Recordings : ComponentBase
{
    [Inject] private IUSB _usb { get; set; }
    [Inject] private ILogger<Recordings> _logger { get; set; }
    [Inject] private IJSRuntime _runtime { get; set; }

    private bool _initialized = false;


    protected override Task OnAfterRenderAsync(bool firstRender)
    {
        if (!_initialized)
        {
            this._usb.OnConnect += OnConnect;
            this._usb.OnDisconnect += OnDisconnect;
            this._usb.Initialize();
            this._initialized = true;
        }
        return Task.CompletedTask;

    }

    protected async Task GetDevices()
    {
        var devices = await this._usb.GetDevices();

        if (devices != null && devices.Length > 0)
        {
            _logger.LogInformation("Device list received");
        }
    }

    private void OnConnect(USBDevice device)
    {
        this._logger.LogInformation("Device connected");
    }

    private void OnDisconnect(USBDevice device)
    {
        this._logger.LogInformation("Device disconnected");
    }
}

即使我按照建议在 OnAfterRenderAsync 中执行 JS 互操作,我仍然会遇到相同的错误。我尝试延迟调用 _usb.Initialize 直到按下按钮(这意味着组件肯定应该已经完成​​渲染。

我尝试通过将 _Host.cshtml 中的渲染模式属性设置为 Server 而不是 ServerPrerendered 来禁用预渲染,但没有任何改变。

【问题讨论】:

    标签: asp.net-core blazor webusb electron.net


    【解决方案1】:

    你的代码应该是这样的:

     protected override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            this._usb.OnConnect += OnConnect;
            this._usb.OnDisconnect += OnDisconnect;
            this._usb.Initialize();
            this._initialized = true;
        }
        return Task.CompletedTask;
    
    }
    

    注意:当 firstRender 变量为 true 时,它​​只出现一次,你可以使用 JSInterop。在此之前你不能。这是初始化 JavaScript 对象的正确时间和地点。

    OnAfterRender(Boolean) 和 OnAfterRenderAsync(Boolean) 生命周期方法对于执行互操作或与从 @ref 接收的值进行交互非常有用。使用 firstRender 参数确保初始化工作只执行一次。

    希望这会有所帮助...

    【讨论】:

    • 其实我就是这么做的。现在我看到了新错误:“无法构建某些服务(验证服务描述符时出错”ServiceType:Blazor.Extensions.WebUSB.IUSB Lifetime:Singleton ImplementationType:Blazor.Extensions.WebUSB.USB':无法使用范围服务来自单例“Blazor.Extensions.WebUSB.IUSB”的“Microsoft.JSInterop.IJSRuntime”。)”
    • 这个新问题与问题标题中描述的当前问题无关。但是,您的服务范围存在问题。 IJSRuntime 的范围是“作用域”,而 IUSB 的范围是“单例”。唯一的解决方案是将 IUSB 范围调整为 IJSRuntime 服务的范围。在 Startup.ConfigureServices 中执行类似的操作: services.AddScoped();而不是 services.AddSingleton();如果它解决了您的问题,您介意将我的答案标记为已接受,以便其他人知道它有用吗?
    猜你喜欢
    • 2014-03-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2015-01-18
    • 2021-05-25
    • 2020-02-13
    • 2013-06-02
    相关资源
    最近更新 更多