使用 Blazor Server 时如何添加客户端 DOM javascript 事件处理程序?
How to add client DOM javascript event handler when using Blazor Server?
...是的,我知道...Blazor 服务器是服务端,我可以在服务器端使用我的 C# 代码处理 DOM 事件...添加纯客户端仍然有意义javascript 事件处理程序,令人惊讶的是它似乎是不可能的,因为 _framework/blazor.server.js 吞噬了它们...
以下是重现我正在做的事情的最简单的独立步骤。
- 使用VS 2019模板创建Blazor App,下一步选择Blazor Server App。
在Index.razor任意位置加一行<div id="test">Hello, click me!</div>
在 _Host.cshtml 中,在已存在的 <script src="_framework/blazor.server.js"></script>
行之后或之前添加以下脚本:
...扯头发,代码块插入不了,这里,看第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>
问题
我错过了什么吗?是否可以在没有服务器往返的情况下完成这项工作?如果不可能,那么许多现有的 javascript 小部件和 jQuery 插件将如何初始化它们?
到目前为止我尝试了什么?
- 例如使用其他事件
mouseup
:不起作用。
- 更改我的自定义脚本和
<script src="_framework/blazor.server.js"></script>
的顺序:两个顺序都不起作用...
- 出于诊断原因注释掉行
<script src="_framework/blazor.server.js"></script>
:事件处理程序现在已调用,我在浏览器中看到控制台输出:"click handler called"
提前回答"why I would like to do this?":
例如,我想实现一个 DOM 行为,在该行为中单击某个元素会更改其属性中的某些内容。我知道,我可以附加一个 C# 处理程序,然后调用返回 javascript 函数,但我不喜欢这种往返。 除此之外,也许有许多现有的 javascript 插件和库依赖于其初始化脚本在 DOM.
上附加事件处理程序
...根据来自火星的 agua 在他的评论中指出的文档:
(如果谁有更好的想法请回答或评论)
如果我 运行 我的客户端脚本附加了事件处理程序 在 服务器 OnAfterRender 事件之后,那么它就可以工作。如果我 运行 它之前以任何方式(例如在 OnInitialized 事件中)它将不起作用:
所以这是一个可行的解决方案:
Index.razor
@code
{
protected override void OnAfterRender(bool firstRender)
{
_jsRuntime.InvokeVoidAsync("attachHandlers");
}
}
_Host.cshtml:
window.attachHandlers = () => {
document.getElementById("test").addEventListener("click", function()
{
console.log("click handler called");
});
};
...是的,我知道...Blazor 服务器是服务端,我可以在服务器端使用我的 C# 代码处理 DOM 事件...添加纯客户端仍然有意义javascript 事件处理程序,令人惊讶的是它似乎是不可能的,因为 _framework/blazor.server.js 吞噬了它们...
以下是重现我正在做的事情的最简单的独立步骤。
- 使用VS 2019模板创建Blazor App,下一步选择Blazor Server App。
在Index.razor任意位置加一行
<div id="test">Hello, click me!</div>
在 _Host.cshtml 中,在已存在的
<script src="_framework/blazor.server.js"></script>
行之后或之前添加以下脚本:...扯头发,代码块插入不了,这里,看第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>
问题
我错过了什么吗?是否可以在没有服务器往返的情况下完成这项工作?如果不可能,那么许多现有的 javascript 小部件和 jQuery 插件将如何初始化它们?
到目前为止我尝试了什么?
- 例如使用其他事件
mouseup
:不起作用。 - 更改我的自定义脚本和
<script src="_framework/blazor.server.js"></script>
的顺序:两个顺序都不起作用... - 出于诊断原因注释掉行
<script src="_framework/blazor.server.js"></script>
:事件处理程序现在已调用,我在浏览器中看到控制台输出:"click handler called"
提前回答"why I would like to do this?":
例如,我想实现一个 DOM 行为,在该行为中单击某个元素会更改其属性中的某些内容。我知道,我可以附加一个 C# 处理程序,然后调用返回 javascript 函数,但我不喜欢这种往返。 除此之外,也许有许多现有的 javascript 插件和库依赖于其初始化脚本在 DOM.
上附加事件处理程序...根据来自火星的 agua 在他的评论中指出的文档: (如果谁有更好的想法请回答或评论)
如果我 运行 我的客户端脚本附加了事件处理程序 在 服务器 OnAfterRender 事件之后,那么它就可以工作。如果我 运行 它之前以任何方式(例如在 OnInitialized 事件中)它将不起作用:
所以这是一个可行的解决方案: Index.razor
@code
{
protected override void OnAfterRender(bool firstRender)
{
_jsRuntime.InvokeVoidAsync("attachHandlers");
}
}
_Host.cshtml:
window.attachHandlers = () => {
document.getElementById("test").addEventListener("click", function()
{
console.log("click handler called");
});
};