从 Blazor 调用 JavaScript:如何在 DotNetObjectReference 中处理 JavaScript?
Calling JavaScript from Blazor: how to dispose JavaScript within DotNetObjectReference?
我创建了一个 Blazor Webassembly 项目并在 JavaScript 中添加了一个关键侦听器,它正在侦听 DOM 文档中的每个击键。 一切都按预期工作,但是,当我打开注册了关键侦听器的 Blazor 页面并稍后再次打开它时,Web 浏览器中出现以下错误:
There is no tracked object with id '2'. Perhaps the
DotNetObjectReference instance was already disposed. (Parameter
'dotNetObjectId')
显然对象“dotnethelper”已被释放,但 Javascript 仍在监听/被调用。
基本上我从 Microsoft Documentation.
实现了“组件实例 .NET 方法助手 class”
Blazor 页面:
注意: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();
}
}
Javascript 文件:
window.initializeKeyListener = (dotnetHelper) => {
document.addEventListener('keydown', logKey);
function logKey(e) {
dotnetHelper.invokeMethod('OnKeyDown', e.key);
console.log('key down ' + e.key);
}
}
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);
}
}
到目前为止我尝试了什么?
- 我尝试重置 window.initializeKeyListener 上的功能(即设置 window.initializeKeyListener),但是这没有实现任何效果
- 我尝试删除 'keydown' 事件的事件监听器。
处理对象时,还需要删除事件侦听器。你提到了 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);
}
然后在您的组件中:
@implements IAsyncDisposable
public async ValueTask DisposeAsync()
{
await JSRuntime.InvokeVoidAsync("removeKeyListener");
objRef?.Dispose();
}
话虽如此,也许使用 [JSInvokable]
在 C# 中调用静态方法更适合您的用例?
我创建了一个 Blazor Webassembly 项目并在 JavaScript 中添加了一个关键侦听器,它正在侦听 DOM 文档中的每个击键。 一切都按预期工作,但是,当我打开注册了关键侦听器的 Blazor 页面并稍后再次打开它时,Web 浏览器中出现以下错误:
There is no tracked object with id '2'. Perhaps the DotNetObjectReference instance was already disposed. (Parameter 'dotNetObjectId')
显然对象“dotnethelper”已被释放,但 Javascript 仍在监听/被调用。
基本上我从 Microsoft Documentation.
实现了“组件实例 .NET 方法助手 class”Blazor 页面:
注意: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();
}
}
Javascript 文件:
window.initializeKeyListener = (dotnetHelper) => {
document.addEventListener('keydown', logKey);
function logKey(e) {
dotnetHelper.invokeMethod('OnKeyDown', e.key);
console.log('key down ' + e.key);
}
}
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);
}
}
到目前为止我尝试了什么?
- 我尝试重置 window.initializeKeyListener 上的功能(即设置 window.initializeKeyListener),但是这没有实现任何效果
- 我尝试删除 'keydown' 事件的事件监听器。
处理对象时,还需要删除事件侦听器。你提到了 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);
}
然后在您的组件中:
@implements IAsyncDisposable
public async ValueTask DisposeAsync()
{
await JSRuntime.InvokeVoidAsync("removeKeyListener");
objRef?.Dispose();
}
话虽如此,也许使用 [JSInvokable]
在 C# 中调用静态方法更适合您的用例?