.net Blazor监听javascript事件

ldioqlga  于 2022-12-24  发布在  .NET
关注(0)|答案(2)|浏览(191)

我有一个javascript事件叫做Hello:

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

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

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

我现在要做的是让事件在一个JavaScript函数中触发,Blazor应该监听事件,而不是JavaScript调用Blazor方法。
希望有人能帮助我。
向我致意,

kiz8lqtg

kiz8lqtg1#

对于自定义事件,您需要手动使用JavaScript/.NET interoperability
使用示例方法调用方法:

  • 通过引用将. NET示例传递给JavaScript:
  • 对DotNetObjectReference.Create进行静态调用。
  • 将该示例 Package 在DotNetObjectReference示例中,并在DotNetObjectReference示例上调用Create。释放DotNetObjectReference对象(本节稍后将给出一个示例)。
  • 使用invokeMethodinvokeMethodAsync函数调用示例上的. NET示例方法。从JavaScript调用其他. NET方法时,也可以将. NET示例作为参数传递。

示例

注意,这是一个非常简化的示例。您可能想添加一些东西;从互操作类to avoid memory leaks上的IDisposable开始。
1.在C#中,创建一个helper类来管理互操作:

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类的示例(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#中的interop的方法:

function addCustomEventListener(dotNetObjectRef) {
  document.addEventListener('hello', (event) => {
    // Calls a method by name with the [JSInokable] attribute (above)
    dotNetObjectRef.invokeMethodAsync('OnCustomEvent')
  });
}

如果使用TypeScript,您可以查看此GitHub问题。

vwkv1x7d

vwkv1x7d2#

对于任何想知道@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; }
}

./wwwroot/index.html内部和<script src="_framework/blazor.webview.js" autostart="false"></script>之后添加JS:

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

在你的剃刀:

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

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

最后,在JS中,您可以分派事件:

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

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

相关问题