Blazor 监听 javascript 事件

Tec*_*iel 8 .net javascript interop webassembly blazor

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

addEventListener('hello', function () {
  alert("event listener");
})
Run Code Online (Sandbox Code Playgroud)

并且,在另一个 javascript 函数中,我引发了该事件:

let event = new Event("hello", { bubbles: true });
document.dispatchEvent(event);
Run Code Online (Sandbox Code Playgroud)

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

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

问候我,

Con*_*Low 11

对于自定义事件,您需要手动利用JavaScript/.NET 互操作性

使用实例方法调用方法:

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

例子

请注意,这是一个非常简化的示例。您可能想添加一些东西;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();
    }
}
Run Code Online (Sandbox Code Playgroud)
  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
}
Run Code Online (Sandbox Code Playgroud)
  1. 在 JavaScript 中,添加一个引用 的方法DotNetObjectReference,并且可以在 C# 中调用互操作:
function addCustomEventListener(dotNetObjectRef) {
  document.addEventListener('hello', (event) => {
    // Calls a method by name with the [JSInokable] attribute (above)
    dotNetObjectRef.invokeMethodAsync('OnCustomEvent')
  });
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我们不要感到困惑,迁移到 .NET6 P2/3 并使用自定义事件类型是“blazor 方式”*但仍处于预览阶段*。其他任何方法都是解决方法。我个人不会使用这种方法,但它肯定会起作用,并且是一种可靠的方法。 (4认同)

Pou*_*tor 10

对于任何想知道 @Mister Magoo 提出的解决方案不再是 .NET 6 预览版的人,这里记录了一些示例。

简而言之 :

使用 EventHandlerAttribute 创建一个 C# 类:

[EventHandler("oncityclicked", typeof(CustomSelectionCityEventArgs),
    enableStopPropagation: true, enablePreventDefault: true)]
public static class EventHandlers
{
}

public class CustomSelectionCityEventArgs: EventArgs
{
    public Guid Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

./wwwroot/index.html在里面和之后添加JS <script src="_framework/blazor.webview.js" autostart="false"></script>

<script>
    Blazor.registerCustomEventType('cityclicked', {
        createEventArgs: event => {
            return {
                id: event.detail
            };
        }
    });
</script>
Run Code Online (Sandbox Code Playgroud)

在你的剃须刀中:

@code {
    private void HandleCityClicked(CustomSelectionCityEventArgs eventArgs)
    {
        Console.WriteLine("Bouep");
    }
}

<div id="CarteLeaflet" @oncityclicked="HandleCityClicked"></div>
Run Code Online (Sandbox Code Playgroud)

最后在 JS 中你可以调度事件:

function OnMarkerClick(pId) {
    const event = new CustomEvent('cityclicked', {
        bubbles: true,
        detail: pId
    });
    document.getElementById('CarteLeaflet').dispatchEvent(event);
}
Run Code Online (Sandbox Code Playgroud)

不要犯和我一样的错误,C#中的事件名称应该以“on”开头(JS:“cityclicked”,C#:“oncityclicked”)。