如何在 Blazor 中执行客户端 UI 事件
How to do client-side UI events in Blazor
我刚刚开始使用 Blazor,我已经可以看到这个新框架的巨大潜力。
不过,我想知道它将如何处理简单的事情,例如将焦点设置在输入控件上?例如,在我处理了一个点击事件之后,我想将焦点设置到一个文本输入控件上。我是否必须使用 JQuery 来处理类似的事情,或者 Blazor 是否会为此类事情提供一些内置方法?
谢谢
更新:我在下面发布了一个答案,其中包含一个示例,说明如何通过从 .Net 代码调用 JavaScript 函数来将焦点设置到控件上。
截至目前(Blazor 0.9.0),您在 Index.html 中创建 JavaScript 函数(或从 Index.html 中引用它们),然后在您的 Blazor 页面或组件中你打电话给 JsRuntime.InvokeAsync("functionName", parms);
https://docs.microsoft.com/en-us/aspnet/core/razor-components/javascript-interop
Blazor 只是 JavaScript 的替代品(更准确地说是“增值”)。这是一个仅 client-side 的解决方案(但它可能会在将来添加一些简单的绑定到 ASP.NET)。
不过,它完全基于 HTML 和 CSS。 C# 正在使用 Web 程序集替换 JS 部分。因此,您访问/修改 HTML 控件的方式没有任何变化。
截至目前(版本 0.1.0)你必须依赖 HTML DOM focus()
方法来做你想做的事(是的你必须使用 JavaScript 截至目前 :( ).
// Not tested code
// This is JavaScript.
// Put this inside the index.html. Just below <script type="blazor-boot"></script>
<script>
Blazor.registerFunction('Focus', (controlId) => {
return document.getElementById(controlId).focus();
});
</script>
//and then wrap it for calls from .NET:
// This is C#
public static object Focus(string controlId)
{
return RegisteredFunction.Invoke<object>("Focus", controlId);
//object type is used since Invoke does not have a overload for void methods. Don't know why.
//this will return undefined according to js specs
}
更多信息,您可以参考下文
如果你想把JS包装的更整齐,你可以这样做:
public class BlazorExtensionScripts : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
builder.OpenElement(0, "script");
builder.AddContent(1, "Blazor.registerFunction('Focus', (controlId) => { document.getElementById(controlId).focus(); });");
builder.CloseElement();
}
public static void Focus(string controlId)
{
RegisteredFunction.Invoke<object>("Focus", controlId);
}
}
然后将此组件添加到根:(App.cshtml
):
<BlazorExtensionScripts></BlazorExtensionScripts>
<Router AppAssembly=typeof(Program).Assembly />
不能直接调用JavaScript函数。您需要先注册您的功能,例如
<script>
Blazor.registerFunction('ShowControl', (item) => {
var txtInput = document.getElementById("txtValue");
txtInput.style.display = "";
txtInput.value = item;
txtInput.focus();
});
return true;
</script>
然后您需要在 C# 中声明一个调用此 JavaScript 函数的方法。喜欢,
private void CallJavaScript()
{
RegisteredFunction.Invoke<bool>("ShowControl", itemName);
}
您可以在单击按钮时调用此 C# 方法。喜欢,
<button id="btnShow" class="btn btn-primary" @onclick(CallJavaScript)>Show</button>
这个postCreate a CRUD App using Blazor and ASP.NET Core
显示了从 Blazor 调用 JavaScript 的工作演示。
我想添加一个更新的(自 0.9.0 起)示例,该示例调用 JavaScript 函数以在某些事件(例如单击按钮)后将焦点设置到另一个控件。这可能对刚开始使用 Blazor 的人(比如我)有帮助。
的 Blazor 文档 "Build Your First Blazor Components App" 中的示例代码
首先,按照文档中的所有说明进行操作。当您有一个可用的待办事项列表页面时,请添加以下内容:
- 在 Index.html 的底部,wwwroot 下,加载 webassembly.js 的脚本标签下方,添加以下脚本:
<script>
window.MySetFocus = (ctrl) => {
document.getElementById(ctrl).focus();
return true;
}
</script>
- 在您的 todo.cshtml 页面顶部,添加以下 using 语句:
@inject IJSRuntime JsRuntime;
- 在 todo.cshtml 页面的 @functions 部分,添加以下函数:
async void Focus(string controlId)
{
var obj = JsRuntime.InvokeAsync<string>(
"MySetFocus", controlId);
}
- 在 AddToDo() 函数中,就在您将 "newToDo" 变量设置为空字符串的行下方,添加对 Focus 函数的调用,并传入输入控件的字符串 ID。 (文档中的例子没有给input控件分配ID,所以自己加一个吧,我的是"todoItem")。
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
Focus("todoItem"); // this is the new code
}
}
- 构建并 运行 您的应用。当您单击添加新项目按钮时,新项目应该被添加到列表中,输入控件消失,焦点应该回到输入控件中,准备添加另一个项目。
来自 .NET 5 预览版 8
Blazor 现在在 ElementReference 上有一个 FocusAsync 便捷方法,用于在该元素上设置 UI 焦点。
<button @onclick="() => textInput.FocusAsync()">Set focus</button>
<input @ref="textInput"/>
我刚刚开始使用 Blazor,我已经可以看到这个新框架的巨大潜力。
不过,我想知道它将如何处理简单的事情,例如将焦点设置在输入控件上?例如,在我处理了一个点击事件之后,我想将焦点设置到一个文本输入控件上。我是否必须使用 JQuery 来处理类似的事情,或者 Blazor 是否会为此类事情提供一些内置方法?
谢谢
更新:我在下面发布了一个答案,其中包含一个示例,说明如何通过从 .Net 代码调用 JavaScript 函数来将焦点设置到控件上。
截至目前(Blazor 0.9.0),您在 Index.html 中创建 JavaScript 函数(或从 Index.html 中引用它们),然后在您的 Blazor 页面或组件中你打电话给 JsRuntime.InvokeAsync("functionName", parms);
https://docs.microsoft.com/en-us/aspnet/core/razor-components/javascript-interop
Blazor 只是 JavaScript 的替代品(更准确地说是“增值”)。这是一个仅 client-side 的解决方案(但它可能会在将来添加一些简单的绑定到 ASP.NET)。
不过,它完全基于 HTML 和 CSS。 C# 正在使用 Web 程序集替换 JS 部分。因此,您访问/修改 HTML 控件的方式没有任何变化。
截至目前(版本 0.1.0)你必须依赖 HTML DOM focus()
方法来做你想做的事(是的你必须使用 JavaScript 截至目前 :( ).
// Not tested code
// This is JavaScript.
// Put this inside the index.html. Just below <script type="blazor-boot"></script>
<script>
Blazor.registerFunction('Focus', (controlId) => {
return document.getElementById(controlId).focus();
});
</script>
//and then wrap it for calls from .NET:
// This is C#
public static object Focus(string controlId)
{
return RegisteredFunction.Invoke<object>("Focus", controlId);
//object type is used since Invoke does not have a overload for void methods. Don't know why.
//this will return undefined according to js specs
}
更多信息,您可以参考下文
如果你想把JS包装的更整齐,你可以这样做:
public class BlazorExtensionScripts : Microsoft.AspNetCore.Blazor.Components.BlazorComponent
{
protected override void BuildRenderTree(Microsoft.AspNetCore.Blazor.RenderTree.RenderTreeBuilder builder)
{
builder.OpenElement(0, "script");
builder.AddContent(1, "Blazor.registerFunction('Focus', (controlId) => { document.getElementById(controlId).focus(); });");
builder.CloseElement();
}
public static void Focus(string controlId)
{
RegisteredFunction.Invoke<object>("Focus", controlId);
}
}
然后将此组件添加到根:(App.cshtml
):
<BlazorExtensionScripts></BlazorExtensionScripts>
<Router AppAssembly=typeof(Program).Assembly />
不能直接调用JavaScript函数。您需要先注册您的功能,例如
<script>
Blazor.registerFunction('ShowControl', (item) => {
var txtInput = document.getElementById("txtValue");
txtInput.style.display = "";
txtInput.value = item;
txtInput.focus();
});
return true;
</script>
然后您需要在 C# 中声明一个调用此 JavaScript 函数的方法。喜欢,
private void CallJavaScript()
{
RegisteredFunction.Invoke<bool>("ShowControl", itemName);
}
您可以在单击按钮时调用此 C# 方法。喜欢,
<button id="btnShow" class="btn btn-primary" @onclick(CallJavaScript)>Show</button>
这个postCreate a CRUD App using Blazor and ASP.NET Core 显示了从 Blazor 调用 JavaScript 的工作演示。
我想添加一个更新的(自 0.9.0 起)示例,该示例调用 JavaScript 函数以在某些事件(例如单击按钮)后将焦点设置到另一个控件。这可能对刚开始使用 Blazor 的人(比如我)有帮助。
的 Blazor 文档 "Build Your First Blazor Components App" 中的示例代码首先,按照文档中的所有说明进行操作。当您有一个可用的待办事项列表页面时,请添加以下内容:
- 在 Index.html 的底部,wwwroot 下,加载 webassembly.js 的脚本标签下方,添加以下脚本:
<script>
window.MySetFocus = (ctrl) => {
document.getElementById(ctrl).focus();
return true;
}
</script>
- 在您的 todo.cshtml 页面顶部,添加以下 using 语句:
@inject IJSRuntime JsRuntime;
- 在 todo.cshtml 页面的 @functions 部分,添加以下函数:
async void Focus(string controlId)
{
var obj = JsRuntime.InvokeAsync<string>(
"MySetFocus", controlId);
}
- 在 AddToDo() 函数中,就在您将 "newToDo" 变量设置为空字符串的行下方,添加对 Focus 函数的调用,并传入输入控件的字符串 ID。 (文档中的例子没有给input控件分配ID,所以自己加一个吧,我的是"todoItem")。
void AddTodo()
{
if (!string.IsNullOrWhiteSpace(newTodo))
{
todos.Add(new TodoItem { Title = newTodo });
newTodo = string.Empty;
Focus("todoItem"); // this is the new code
}
}
- 构建并 运行 您的应用。当您单击添加新项目按钮时,新项目应该被添加到列表中,输入控件消失,焦点应该回到输入控件中,准备添加另一个项目。
来自 .NET 5 预览版 8
Blazor 现在在 ElementReference 上有一个 FocusAsync 便捷方法,用于在该元素上设置 UI 焦点。
<button @onclick="() => textInput.FocusAsync()">Set focus</button>
<input @ref="textInput"/>