从 Blazor 调用 JavaScript:如何在 DotNetObjectReference 中处理 JavaScript?

Fab*_*ler 5 javascript c# blazor-webassembly

我创建了一个 Blazor Web assembly 项目,并在 JavaScript 中添加了一个关键侦听器,该侦听器侦听 DOM 文档上的每个击键。一切都按预期进行,但是当我打开注册了密钥侦听器的 Blazor 页面并稍后再次打开它时,Web 浏览器中会出现以下错误:

没有 ID 为“2”的跟踪对象。也许 DotNetObjectReference 实例已经被释放。(参数“dotNetObjectId”)

显然,对象“dotnethelper”已被释放,但 Javascript 仍在侦听/被调用。

基本上,我实现了Microsoft 文档中的“组件实例 .NET 方法帮助器类” 。

开拓者页面:

注意:IDisposable 被注入到顶部,并且 Dispose 函数被调用。

@code {
    private KeyListenerInvokeHelper _keyListenerInvokeHelper;
    private DotNetObjectReference<KeyListenerInvokeHelper>? objRef;

    protected override async Task OnInitializedAsync()
    {
        objRef = DotNetObjectReference.Create(_keyListenerInvokeHelper);
        await JS.InvokeVoidAsync("initializeKeyListener", objRef);    
    }

    public void Dispose()
    {
        objRef?.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

JavaScript 文件:

window.initializeKeyListener = (dotnetHelper) => {
    document.addEventListener('keydown', logKey);
    function logKey(e) {     
        dotnetHelper.invokeMethod('OnKeyDown', e.key);
        console.log('key down ' + e.key);
    }
}
Run Code Online (Sandbox Code Playgroud)

KeyListenerInvokeHelper:

public class KeyListenerInvokeHelper
{
    private readonly Action<string> action;

    public KeyListenerInvokeHelper(Action<string> action)
    {
        this.action = action;
    }

    [JSInvokable("OnKeyDown")]
    public void OnKeyDown(string key)
    {
        action.Invoke(key);
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止我尝试过什么?

  • 我尝试重置 window.initializeKeyListener 上的函数(即设置 window.initializeKeyListener),但这没有实现任何目标
  • 我尝试删除“keydown”事件上的事件侦听器。

Jes*_*ood 6

当您处置对象时,您还需要删除事件侦听器。你提到了I tried removing the eventlistener on the 'keydown' event.,但也许你的做法不正确?我的 javascript 有点生疏,但我认为你可以这样做:

var logkey;
window.initializeKeyListener = (dotnetHelper) => {
    logkey = (e) => {
        dotnetHelper.invokeMethod('OnKeyDown', e.key);
        console.log('key down ' + e.key);
    };
    document.addEventListener('keydown', logkey);
}

window.removeKeyListener = () => {
    document.removeEventListener('keydown', logkey);
}
Run Code Online (Sandbox Code Playgroud)

然后在你的组件中:

@implements IAsyncDisposable

public async ValueTask DisposeAsync()
{
    await JSRuntime.InvokeVoidAsync("removeKeyListener");
    objRef?.Dispose();
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,也许使用 C# 调用静态方法[JSInvokable]更适合您的用例?

  • 请注意,对于 BLAZOR SERVER 来说,这会遇到以下问题:重新加载页面时(或只需单击主页按钮转到空白),这将导致“Microsoft.JSInterop.JSDisconnectedException:”此时无法发出 JavaScript 互操作调用。这是因为电路已断开连接并正在处理。'`请参阅:/sf/ask/5074199441/ throwing-system-invalidoperationexception-javas https://github.com /dotnet/aspnetcore/问题/33336 (2认同)