大家好,我是Edison。

上一篇我们学习了Blazor+SignalR开发简单的实时应用程序,这一篇我们了解下Blazor和JavaScript的互操作性。

有了Blazor还需要JavaScript?

我们都知道,在Blazor中我们可以轻松地使用C#组件而不是JavaScript来创建Web应用程序,但是,这并不代表我们不能继续使用JavaScript提供的便利。很

多时候,我们可能希望继续使用JavaScript提供的函数来实现某些功能,这时,我们可以用Blazor和JavaScript的互操作性(也称为JS互操作)来调用Blazor应用中的JavaScript库,并从C#代码直接调用JavaScript函数。当然,也可以使用JS互操作性从JavaScript函数调用C#方法。

这种场景经常发生在:有时候需要使用现有的JavaScript库,例如一些开源JavaScript库以专门的方式呈现组件和处理用户界面元素,又或者你可能拥有一些开源JavaScript库的开发调试经验,是个JavaScript库的老鸟了,你希望重用该JavaScript代码而不是将其转换为C#。那么,这个时候,你可能就需要用上JS互操作性了。

接下来,我们就来看看如何在Blazor应用中加载JavaScript代码,又如何在JavaScript中调用.NET代码。

在Blazor中调用JavaScript代码

加载方式

将JavaScript添加到Blazor应用的方式与添加到标准HTML Web应用一样,都是使用HTML的<script>元素。我们可以在 Pages/_Layout.cshtml 文件或 wwwroot/index.html文件中的现有 <script src="_framework/blazor.*.js"></script> 标记后添加 <script> 标记即可。

NOTE:最好不要将JavaScript脚本放在页面的<head>元素中。

将JavaScript库或脚本添加之后,我们就可以在C#代码中通过使用 IJSRuntime 接口调用JavaScript函数了。不过,你需要提前将 IJSRuntime 实例注入Blazor页面中。

IJSRuntime 接口用于调用JavaScript代码的 InvokeAsync(有返回值) 和 InvokeVoidAsync(无返回值) 两个方法。顾名思义,这两个方法都是异步的,因此你需要在使用时标注await来获取结果。

InvokeAsync 或 InvokeVoidAsync 方法的接收参数,第一个是要调用的JavaScript函数的名称,比如 confirm 这个方法名。第二个则是这个函数所需的任何参数。

需要注意的是:

  • JavaScript函数必须属于 window 作用域 或 window 子作用域;

  • 传入的参数必须是可序列化为JSON的;

DEMO

假设我们已经有了一个Blazor Server应用程序,你可以从这里获取Code:https://github.com/Coder-EdisonZhou/BlazorSamples

这里我们改写一下经典的Counter页面,将原来的按钮直接加一改为调用JavaScript的confirm函数弹出一个确认框,确认后再加一。

为了实现这个功能,我们需要改写如下:

Step1. 注入IJSRuntime抽象实例

[Inject]
public IJSRuntime JavaScript { get; set; }

Step2. 改写原来的button按钮调用IncrementCountConfirmation方法

@* <button class="btn btn-primary" @onclick="IncrementCount">Click me</button> *@
<button class="btn btn-primary" @onclick="@(async() => await IncrementCountConfirmation())">Click me</button>

Step3. 实现IncrementCountConfirmation方法

@code {
private int currentCount = 0; [Parameter]
public int IncrementAmount { get; set; } = 1; [Inject]
public IJSRuntime JavaScript { get; set; } private void IncrementCount()
{
currentCount += IncrementAmount;
} private async Task IncrementCountConfirmation()
{
if (await JavaScript.InvokeAsync<bool>(
"confirm",
"Do you want to increment the count?"))
{
currentCount += IncrementAmount;
}
}
}

最终的效果如下图:

那么,如果想要使用第三方JavaScript库的函数该如何做呢?

你只需要在 Pages/_Layout.cshtml 文件的末尾,在现有 <script src="_framework/blazor.*.js"></script> 标记后添加你需要引入的JavaScript库即可。
然后,你就可以在C#代码中继续通过 IJSRuntime 调用第三方JavaScript库中的函数了。

在JavaScript中调用C#代码

加载方式

在JavaScript中若想调用C#代码可以使用 DotNet实用工具类(JS互操作的一部分)来运行Blazor代码中定义的.NET方法。在这个工具类中提供了 invokeMethod 和 invokeMethodAsync 两个函数,顾名思义,一个是同步的,另一个是异步的。

invokeMethodAsync方法返回 JavaScript Promise。

需要注意的是:

  • 要调用的.NET方法需要使用 JSInvokableAttribute 标记

  • 且该方法必须是 public的

  • 且该方法任何参数都必须可序列化为JSON

DEMO

这里我们还是改写一下刚刚的Counter页面,增加一个button用于在JavaScript中调用.NET静态方法。

Step1. 添加HTML与JavaScript

<h1>Call .NET Example From JavaScript</h1>

<p>
<button onclick="returnArrayAsync()">
Trigger .NET static method
</button>
</p> <script>
window.returnArrayAsync = () => {
DotNet.invokeMethodAsync('EDT.BlazorServer.App', 'ReturnArrayAsync')
.then(data => {
console.log(data);
});
};
</script>

Step2. 添加.NET方法并标注 JSInvokable

[JSInvokable]
public static Task<int[]> ReturnArrayAsync()
{
return Task.FromResult(new int[] { 1, 2, 3 });
}

效果演示:

那么,如果是.NET实例方法,该如何调用呢?这个就稍微复杂一丢丢了。

还是来个Demo吧:

Step1. 添加HTML和JavaScript示例:

<h1>Call .NET Example From JavaScript - Sample 2</h1>

<p>
<label>
Name: <input @bind="name" />
</label>
</p> <p>
<button @onclick="TriggerDotNetInstanceMethod">
Trigger .NET instance method
</button>
</p> <p>
@result
</p> <script>
window.sayHello = (dotNetHelper) => {
return dotNetHelper.invokeMethodAsync('GetHelloMessage');
};
</script>

Step2. 添加.NET方法并标注 JSInvokable,还需要声明一个 DotNetObjectReference对象便于进行资源释放,以免引起内存泄露的问题;

@code {
[Inject]
public IJSRuntime JavaScript { get; set; } private string? name;
private string? result;
private DotNetObjectReference<Counter>? objRef; protected override void OnInitialized()
{
objRef = DotNetObjectReference.Create(this);
} public async Task TriggerDotNetInstanceMethod()
{
result = await JavaScript.InvokeAsync<string>("sayHello", objRef);
} [JSInvokable]
public string GetHelloMessage() => $"Hello, {name}!"; public void Dispose()
{
objRef?.Dispose();
}
}

效果演示:

小结

本篇,我们了解了什么是Blazor中的JS互操作,并通过两个DEMO了解了如何在Blazor中加载JavaScript代码 以及 如何在JavaScript中调用.NET代码,相信对你会有所帮助。

参考代码

GitHub:https://github.com/EdisonChou/BlazorSamples/tree/main

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

Blazor学习之旅(12) JavaScript与Blazor的互操作的更多相关文章

  1. python学习之旅1-2(基础知识)

    三,python基础初识. 1.运行python代码. 在d盘下创建一个t1.py文件内容是: print('hello world') 打开windows命令行输入cmd,确定后 写入代码pytho ...

  2. 笔记-JavaWeb学习之旅12

    会话技术 Cookie:客户端会话技术,将数据保存到客户端 package com.data.Cookie; import javax.servlet.ServletException; import ...

  3. 学习MASA第一天:MASA Blazor TEST项目创建

    个人博客地址: https://note.raokun.top 拥抱ChatGPT,国内访问网站:https://www.playchat.top 学习MASA第一天:MASA Blazor TEST ...

  4. Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  5. [推荐]大量 Blazor 学习资源(二)

    继上一篇<[推荐]大量 Blazor 学习资源(一)>之后,社区反应不错,但因个人原因导致这篇文章姗姗来迟,不过最终还是来了!这篇文章主要收集一些常用组件.书籍和电子书. 资料来源:htt ...

  6. WCF学习之旅—实现支持REST客户端应用(二十四)

    WCF学习之旅—实现REST服务(二十二) WCF学习之旅—实现支持REST服务端应用(二十三) 在上二篇文章中简单介绍了一下RestFul与WCF支持RestFul所提供的方法,及创建一个支持RES ...

  7. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  8. WCF学习之旅—WCF第二个示例(五)

    二.WCF服务端应用程序 第一步,创建WCF服务应用程序项目 打开Visual Studio 2015,在菜单上点击文件—>新建—>项目—>WCF服务应用程序.在弹出界面的“名称”对 ...

  9. 我的AngularJS 学习之旅

    我的AngularJS 学习之旅 基础篇 1.Angular的 起源 2.比较Web 页面实现的几种方式 3.一些基本术语 4.Angular与其他框架的兼容性 5.总结 6.综合实例   很早之前就 ...

  10. 180分钟的python学习之旅

    最近在很多地方都可以看到Python的身影,尤其在人工智能等科学领域,其丰富的科学计算等方面类库无比强大.很多身边的哥们也提到Python非常的简洁方便,比如用Django搭建一个见得网站只需要半天时 ...

随机推荐

  1. mosquitto的基本参数使用

    当使用mosquitto_pub命令时,可以使用多个参数来配置发布行为.以下是mosquitto_pub命令的一些常见参数及其详细说明: -h, --host <hostname>:指定连 ...

  2. Linux终端居然也可以做文件浏览器?

    大家好,我是良许. 在抖音上做直播已经整整 5 个月了,我很自豪我一路坚持到了现在[笑脸] 最近我在做直播的时候,也开始学习鱼皮大佬,直播写代码.当然我不懂 Java 后端,因此就写写自己擅长的 Sh ...

  3. Clion配置Fortran环境

    1.安装CLion 下载链接:https://www.jetbrains.com/ 下载好后安装到指定目录即可 2.安装Fortran插件 3.编写程序 1)打开CLion,新建一个Fortran项目 ...

  4. ArrayBlockingQueue的take()底层原理

    一.ArrayBlockingQueue 的 take() 方法的底层源码的详细介绍 ArrayBlockingQueue 是 Java 并发包 (java.util.concurrent) 中的一个 ...

  5. PIKACHU之暴力破解

    PIKACHU之暴力破解 基于表单的暴力破解 进入靶场后是一个简易的登录界面 随便输入用户名与密码观察回显 由于回显是模糊回显,并没有表示是用户名错误还是密码错误,直接进入BP采用暴力破解,但是在进行 ...

  6. 关于symfony报错: Oops An Error Occurred ,The server returned a “500 Internal Server Error“

    symfony3.4 开发环境正常,生产环境访问任何路由都报错: Oops! An Error Occurred The server returned a "500 Internal Se ...

  7. MVVM绑定 填坑,必须在与 DependencyObject 相同的线程上创建 DependencySource

    场景:线程里面构建MVVM实体类,实体类包含 Brush 属性时,构建 SolidColorBrush 需要UI线程,否则会报 "必须在与 DependencyObject 相同的线程上创建 ...

  8. lighttools batchmode 批处理vb程序代码

    完成后的图示,选择需要模拟的lighttools后,直接进行运行,点击开始模拟,即可逐个模拟完成 lighttools 连接代码: 1 Private m_ltServer As LTAPI 2 3 ...

  9. 2.1k star! 抓紧冲,DeepChat:连接AI与个人世界的智能助手的开源项目

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 DeepChat是一款开源的跨平台智能助手工具,它如同AI世界的"万能转换插头&q ...

  10. 百图生科:基于 JuiceFS 构建生命科学大模型存储平台,成本降 90%

    百图生科(BioMap)由百度创始人李彦宏先生联合创立,专注于生命科学领域的人工智能技术.公司推出了全球最大的生命科学 AI 基础模型 xTrimo V3,拥有 2100 亿参数,覆盖蛋白质.DNA. ...