使用 Blazor 服务器时如何添加客户端 DOM javascript 事件处理程序?

g.p*_*dou 6 javascript dom dom-events blazor blazor-server-side

...是的,我知道... Blazor 服务器是服务端,我可以在服务器端用我的 C# 代码处理 DOM 事件...添加纯客户端 javascript 事件处理程序仍然有意义,而且令人惊讶的是它似乎是不可能,因为 _framework/blazor.server.js 吞下了它们......

以下是重现我在做什么的最简单的孤立步骤。

  1. 使用 VS 2019 模板创建 Blazor 应用程序,在下一步中选择 Blazor 服务器应用程序。
  2. 在 Index.razor 中的任意位置添加一行 <div id="test">Hello, click me!</div>

  3. 在 _Host.cshtml 中,在已经存在的文件之后或之前添加以下脚本 <script src="_framework/blazor.server.js"></script>行:

    ...拉我的头发,我不能插入代码块,在这里,看第4步之后...

  4. 运行应用程序,然后按 F12 以查看控制台输出。

这是步骤 3 中的脚本:

<script>
    console.log("script is executing...");
    console.log("element found, its innerText is: " + document.getElementById("test").innerText);

    document.getElementById("test").addEventListener("click",
        function() {
            console.log("click handler called");
        });
</script>
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

我错过了什么吗?是否可以在没有服务器往返的情况下完成这项工作?如果不可能,那么许多现有的 javascript 小部件和 jQuery 插件将如何初始化自己?

到目前为止我尝试过什么?

  • 例如使用其他事件mouseup:不起作用。
  • 更改我的自定义脚本的顺序和<script src="_framework/blazor.server.js"></script>:两个顺序都不起作用...
  • 出于<script src="_framework/blazor.server.js"></script>诊断原因注释掉该行:现在调用了事件处理程序,我在浏览器中看到控制台输出:“单击处理程序调用”

提前回答“我为什么要这样做?”:

例如,我想实现一个 DOM 行为,其中单击一个元素会更改其属性中的某些内容。我知道,我可以附加一个 C# 处理程序,然后回调一个 javascript 函数,但我不喜欢这种往返。除此之外,可能有许多现有的 javascript 插件和库依赖于其初始化脚本在 DOM 上附加事件处理程序。

g.p*_*dou 2

...基于来自火星的 agua 在他的评论中指出的文档:(如果有人有更好的想法,请回答或评论)

如果我运行在服务器 OnAfterRender 事件之后附加事件处理程序的客户端脚本,那么它就可以工作。如果我之前以任何方式运行它(例如在 OnInitialized 事件中),它将不起作用:

所以这是一个可行的解决方案:Index.razor

@code
{
    protected override void OnAfterRender(bool firstRender)
    {
        _jsRuntime.InvokeVoidAsync("attachHandlers");
    }
}
Run Code Online (Sandbox Code Playgroud)

_主机.cshtml:

window.attachHandlers = () => {
    document.getElementById("test").addEventListener("click", function()
    {
         console.log("click handler called");
    });
};
Run Code Online (Sandbox Code Playgroud)