You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor Server键盘控制:解决dotNetReference持久化与事件重复问题

Blazor Server键盘控制解决方案

问题根源

  1. 匿名函数重复触发:OnAfterRenderAsync会在每次组件渲染时执行,若未加firstRender判断,会重复绑定keyup事件,导致每次按键触发多次回调。
  2. 命名函数丢失引用:在自定义命名函数内重新声明var dotNetReference = dotNetReference,因变量提升规则,局部变量会覆盖外部引用且初始值为undefined,无法正常调用C#方法。

正确实现步骤

1. C#组件代码(修复重复绑定+内存管理)

public class YourComponent : ComponentBase, IDisposable
{
    [Inject]
    protected IJSRuntime JSRuntime { get; set; } = default!;

    private DotNetObjectReference<YourComponent>? _dotNetReference;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        // 仅在第一次渲染时绑定事件,避免重复绑定
        if (firstRender)
        {
            _dotNetReference = DotNetObjectReference.Create(this);
            await JSRuntime.InvokeVoidAsync("JsFunctions.addKeyboardListener", _dotNetReference);
        }
    }

    [JSInvokable]
    public void Next()
    {
        ClearMessages();
    }

    [JSInvokable]
    public void Prev()
    {
        // 实现Prev逻辑
    }

    [JSInvokable]
    public void NavigateToOverviewPage()
    {
        // 实现导航逻辑
    }

    // 组件销毁时释放引用并解绑事件,避免内存泄漏
    public void Dispose()
    {
        _dotNetReference?.Dispose();
        _ = JSRuntime.InvokeVoidAsync("JsFunctions.removeKeyboardListener");
    }

    private void ClearMessages()
    {
        // 你的业务逻辑
    }
}

2. JavaScript代码(持久化引用+支持解绑)

window.JsFunctions = {
    addKeyboardListener: function (dotNetReference) {
        // 闭包捕获外部的dotNetReference,无需重新声明
        function handleKeyUp(event) {
            // 注意:event.key是字符值(如"7"),event.keyCode是数字键码(如数字键7对应55),根据实际需求调整
            if (event.key === "7") {
                dotNetReference.invokeMethodAsync('Prev');
            }
            if (event.key === "8") {
                dotNetReference.invokeMethodAsync('Next');
            }
            if (event.key === "3") {
                dotNetReference.invokeMethodAsync('NavigateToOverviewPage');
            }
        }
        document.addEventListener('keyup', handleKeyUp);
        // 存储监听函数,用于后续解绑
        window._keyboardHandler = handleKeyUp;
    },
    removeKeyboardListener: function () {
        if (window._keyboardHandler) {
            document.removeEventListener('keyup', window._keyboardHandler);
            window._keyboardHandler = null;
        }
    }
};

关键说明

  • 闭包捕获引用:命名函数handleKeyUp直接使用外部函数传入的dotNetReference,确保引用持久化可用。
  • 避免重复绑定:通过firstRender判断,仅在组件首次渲染时执行事件绑定逻辑。
  • 内存泄漏防护:实现IDisposable接口,在组件销毁时释放DotNetObjectReference并解绑事件,避免内存泄漏。

内容的提问来源于stack exchange,提问作者boxofgiraffes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 20:22:52