【问题标题】:Blazor listen to javascript eventBlazor 监听 javascript 事件
【发布时间】:2021-05-18 22:26:55
【问题描述】:

我有一个名为 Hello 的 javascript 事件:

addEventListener('hello', function () {
  alert("event listener");
})

并且,在另一个 javascript 函数中,我提出了事件:

let event = new Event("hello", { bubbles: true });
document.dispatchEvent(event);

我现在要做的是让事件在 javascript 函数中触发。 Blazor 应该监听事件,而不是调用 Blazor 方法的 javascript。

希望任何人都可以帮助我。

问候我,

【问题讨论】:

  • 您使用的是什么版本的 .NET?
  • 我正在使用 .Net 5.0
  • 我之所以这么问,是因为 .NET 6 preview 2 向 Blazor 引入了自定义事件类型。在那之前,如果您想处理像您这样的自定义事件,您需要通过让您的自定义事件处理程序调度您正在侦听的标准事件来“欺骗” blazor,例如在您的 Blazor 代码中包含 <div id='foo' @onchange=HandleHello></div> 之类的内容,然后在您的 JS 代码中,每当您捕获 hello 事件时,将 change 事件发送到 foo
  • 感谢您的提示。我仍然可以更改为版本 6 prev 2 我刚刚开始构建应用程序。你的建议是什么?
  • 转到.NET 6 preview 3,然后你可以这样做:devblogs.microsoft.com/aspnet/…

标签: javascript .net blazor interop webassembly


【解决方案1】:

对于自定义事件,您需要手动使用JavaScript/.NET interoperability

使用Instance Method Call 方法:

  • 通过引用 JavaScript 传递 .NET 实例:
    • 对 DotNetObjectReference.Create 进行静态调用。
    • 将实例包装在 DotNetObjectReference 实例中并在 DotNetObjectReference 实例上调用 Create。处理 DotNetObjectReference 对象(本节后面会显示一个示例)。
  • 使用invokeMethodinvokeMethodAsync 函数在实例上调用.NET 实例方法。从 JavaScript 调用其他 .NET 方法时,也可以将 .NET 实例作为参数传递。

示例

注意,这是一个非常简化的示例。您可能想添加一些东西;在您的互操作类 to avoid memory leaks 上从 IDisposable 开始。

  1. 在 C# 中,创建一个帮助类来管理互操作:
public class CustomEventHelper
{
    private readonly Func<EventArgs, Task> _callback;

    public CustomEventHelper(Func<EventArgs, Task> callback)
    {
        _callback = callback;
    }

    [JSInvokable]
    public Task OnCustomEvent(EventArgs args) => _callback(args);
}

public class CustomEventInterop : IDisposable
{
    private readonly IJSRuntime _jsRuntime;
    private DotNetObjectReference<CustomEventHelper> Reference;

    public CustomEventInterop(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public ValueTask<string> SetupCustomEventCallback(Func<EventArgs, Task> callback)
    {
        Reference = DotNetObjectReference.Create(new ScrollEventHelper(callback));
        // addCustomEventListener will be a js function we create later
        return _jsRuntime.InvokeAsync<string>("addCustomEventListener", Reference);
    }

    public void Dispose()
    {
        Reference?.Dispose();
    }
}
  1. 在 Blazor 组件中,添加互操作类的实例 (Interop) 并添加本地方法作为回调 (HandleCustomEvent):
private CustomEventInterop Interop { get; set; }

protected override async Task OnAfterRenderAsync(bool firstRender) {
    if (!firstRender)
    {
        return;
    }
    Interop = new(JS);
    await Interop.SetupCustomEventCallback(args => HandleCustomEvent(args));
    HasRendered = true;
}

private void HandleCustomEvent(EventArgs args) {
    // ... handle custom event here
}
  1. 在 JavaScript 中,添加一个引用 DotNetObjectReference 的方法,并且可以在 C# 中调用互操作:
function addCustomEventListener(dotNetObjectRef) {
  document.addEventListener('hello', (event) => {
    // Calls a method by name with the [JSInokable] attribute (above)
    dotNetObjectRef.invokeMethodAsync('OnCustomEvent')
  });
}

如果使用 TypeScript,您可以查看GitHub Issue

【讨论】:

  • 我只想订阅在 javascript 中创建的事件。没有使用按钮或 ui 元素。它就像观察者模式
  • 是的,您必须为此使用 JS Interop。从 .NET 5 开始,这是在 blazor 中侦听自定义事件的唯一方法。
  • @enet 除非您使用 .NET 6 预览版,否则 JS 互操作是处理真实自定义事件的最佳方式。 mrmagoo 的 hack 可能有效,但它仍然是:一个 hack。
  • 不要混淆,迁移到 .NET6 P2/3 并使用自定义事件类型是“blazor 方式”但仍处于预览阶段。其他任何方法都是一种解决方法。我个人不会使用这种方法,但它肯定会奏效,而且是一种可靠的方法。
  • 没错,这并不是在 Blazor 中使用 JS 互操作实现事件侦听器的唯一方法。在 .NET 6 发布之前,我认为 JS 互操作是解决问题的最可靠方法。它甚至可以扩展为接受来自 js 的可序列化有效负载,而 @onclick 解决方法无法做到这一点。如果您不需要任何花哨的东西,那么@mister magoo 也为您提供了一个很好的解决方法。我怀疑 .NET 6 发布后会有更多吸引人的答案。
猜你喜欢
  • 2020-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 2012-09-13
  • 2013-07-21
相关资源
最近更新 更多