Window Event Listener

JS interop, JSinterop, IJSRuntime, IAsyncDisposable, jsModule, DotNetObjectReference, IJSObjectReference, BlazorComponent.razor.js 資源釋放等。

引言

開發 Blazor 共用元件專用於監聽 Brower Window Events,如:focus 以操作 App。

為工作紀錄。

關鍵程式碼紀錄

Blazor 元件,放在共享目錄 Shared

WindowEventListener.razor
@*
 * 監聽 Browser Window 訊息。
 * 現在只支援監聽 window.focus 訊息。
 * ※注意:建議放置在 page 層級,且只放一個。若同時放置多處只有最後一個有效。
*@

@using Microsoft.JSInterop
@implements IAsyncDisposable
@inject IJSRuntime jsr

@code {
  [Parameter] public EventCallback OnFocus { get; set; }

  //## Resource
  DotNetObjectReference<WindowEventListener>? dotNetObject;
  IJSObjectReference? jsModule;

  public async ValueTask DisposeAsync()
  {
    if (jsModule != null)
    {
      // 反註冊監聽 Browser Window 訊息
      await jsModule.InvokeVoidAsync("unregisterWindowEventHandler");
      // 釋放資源
      await jsModule.DisposeAsync();
    }

    dotNetObject?.Dispose();
  }

  protected override async Task OnAfterRenderAsync(bool firstRender)
  {
    if (firstRender)
    {
      dotNetObject = DotNetObjectReference.Create(this);
      jsModule = await jsr.InvokeAsync<IJSObjectReference>(
        "import", "./Shared/WindowEventListener.razor.js");

      // 註冊監聽 Browser Window 訊息
      await jsModule.InvokeVoidAsync("registerWindowEventHandler", dotNetObject);
    }
  }

  [JSInvokable]
  public Task OnWindowFocus() => OnFocus.InvokeAsync();
}

Blazor 元件關聯的 JavaScript code。 依部署對應規則將會部署到:./Shared/WindowEventListener.razor.js

WindowEventListener.razor.js
let _dotNetObject = null;

function onFocus(event) {
  // events up
  console.debug('window.onFocus =>', _dotNetObject);
  _dotNetObject && _dotNetObject.invokeMethodAsync("OnWindowFocus");
}

export async function registerWindowEventHandler(dotNetObject) {
  _dotNetObject = dotNetObject;
  console.debug('註冊監聽訊息…', dotNetObject);
  window.addEventListener("focus", onFocus);
}

export async function unregisterWindowEventHandler() {
  console.debug('反註冊監聽訊息…', _dotNetObject);
  window.removeEventListener("focus", onFocus);
  _dotNetObject = null;
}

應用:每當使用者 focus 進此 page 皆重新刷新頁面以重取最新狀態。

FooPage.razor
@page "/foopage"
@inject NavigationManager navSvc

<MudContainer>
  [...page content...]
</MudContainer>

<WindowEventListener OnFocus=HandleWindowFocus />

@code {
  ...[略]...

  Task HandleWindowFocus()
  {
    //※ 每當使用者 focus 進此 page 皆重新刷新頁面以重取最新狀態。
    navSvc.NavigateTo(navSvc.Uri, true); // reload this page.
    return Task.CompletedTask;
  }
}

參考文件

Last updated