简体   繁体   English

Blazor 监听 javascript 事件

[英]Blazor listen to javascript event

I have a javascript event called Hello:我有一个名为 Hello 的 javascript 事件:

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

and, in another javascript function, I raise the event:并且,在另一个 javascript 函数中,我引发了事件:

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

What I want to do now is let the event trigger in a javascript function.我现在要做的是让事件在 javascript 函数中触发。 Blazor should listen to the event, not javascript calling a Blazor method. Blazor 应该监听事件,而不是调用 Blazor 方法的 javascript。

Hope anyone can assist me.希望任何人都可以帮助我。

Regards me,问候我,

For custom events, you will need to manually utilize JavaScript/.NET interoperability .对于自定义事件,您需要手动利用JavaScript/.NET 互操作性

Using the Instance Method Call method:使用实例方法调用方法:

  • Pass the .NET instance by reference to JavaScript:通过引用 JavaScript 传递 .NET 实例:
    • Make a static call to DotNetObjectReference.Create.对 DotNetObjectReference.Create 进行 static 调用。
    • Wrap the instance in a DotNetObjectReference instance and call Create on the DotNetObjectReference instance.将实例包装在 DotNetObjectReference 实例中并在 DotNetObjectReference 实例上调用 Create。 Dispose of DotNetObjectReference objects (an example appears later in this section).处理 DotNetObjectReference 对象(本节后面会显示一个示例)。
  • Invoke .NET instance methods on the instance using the invokeMethod or invokeMethodAsync functions.使用invokeMethodinvokeMethodAsync函数在实例上调用 .NET 实例方法。 The .NET instance can also be passed as an argument when invoking other .NET methods from JavaScript.当从 JavaScript 调用其他 .NET 方法时,.NET 实例也可以作为参数传递。

Example例子

Note, this is a very simplified example.请注意,这是一个非常简化的示例。 You probably want to add a few things;您可能想添加一些东西; start by IDisposable on your interop classes to avoid memory leaks .从您的互操作类上的IDisposable开始, 以避免 memory 泄漏

  1. In C#, create a helper class to manage the interop:在 C# 中,创建一个帮助程序 class 来管理互操作:
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. In a Blazor component, add an instance of the interop class ( Interop ) and add a local method as a callback ( HandleCustomEvent ):在 Blazor 组件中,添加互操作 class ( 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. In JavaScript, add a method that references the DotNetObjectReference and can call the interop in C#:在JavaScript中,添加一个引用DotNetObjectReference的方法,可以调用C#中的互操作:
function addCustomEventListener(dotNetObjectRef) {
  document.addEventListener('hello', (event) => {
    // Calls a method by name with the [JSInokable] attribute (above)
    dotNetObjectRef.invokeMethodAsync('OnCustomEvent')
  });
}

If using TypeScript, you might check out this GitHub Issue .如果使用 TypeScript,您可以查看此GitHub 问题

For anyone wondering the solution proposed by @Mister Magoo is no longer a preview for .NET 6 and is documented here with some exemples.对于任何想知道@Mister Magoo 提出的解决方案不再是 .NET 6 的预览并且在此处记录了一些示例的人。

In a nutshell:简而言之:

Create a C# class with the EventHandlerAttribute:使用 EventHandlerAttribute 创建一个 C# 类:

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

public class CustomSelectionCityEventArgs: EventArgs
{
    public Guid Id { get; set; }
}

Add JS inside ./wwwroot/index.html and after <script src="_framework/blazor.webview.js" autostart="false"></script> :./wwwroot/index.html<script src="_framework/blazor.webview.js" autostart="false"></script>之后添加 JS:

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

In you razor:在你的剃须刀中:

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

<div id="CarteLeaflet" @oncityclicked="HandleCityClicked"></div>

And finally in the JS you can dispatch the event:最后在 JS 中你可以发送事件:

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

Don't make the same mistake as me, the event name in the C# should start with "on" (JS: "cityclicked", C#: "oncityclicked").不要和我犯同样的错误,C#中的事件名称应该以“on”开头(JS:“cityclicked”,C#:“oncityclicked”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM