Вызов javascript из Blazor приводит к ошибке
У меня есть приложение Blazor, построенное на.NET Core 3.1, и мне нужно иметь доступ к ресурсам 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");
}
}
И хотя я выполняю JS-взаимодействие в OnAfterRenderAsync, как было предложено, я все равно получаю ту же ошибку. Я попытался отложить вызов _usb.Initialize до тех пор, пока не будет нажата кнопка (это означает, что компонент определенно должен завершить рендеринг.
Я попытался отключить предварительную отрисовку, установив атрибут режима рендеринга в _Host.cshtml на Server вместо ServerPrerendered, но ничего не изменилось.
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, чтобы гарантировать, что инициализация выполняется только один раз.
Надеюсь это поможет...