Blazor作为微软推出的基于.NET的前端框架,支持开发者使用C#编写前端逻辑,但在实际开发中,难免会遇到需要调用JavaScript函数的情况,比如操作DOM、使用第三方JS库或者调用浏览器特有的API。Blazor提供了JS互操作机制,通过IJSRuntime接口就能实现C#代码调用JavaScript函数的需求。

调用前的准备工作
首先需要在项目中引入JS互操作的相关依赖,Blazor框架默认已经集成了IJSRuntime接口,不需要额外安装NuGet包。接下来需要在wwwroot目录下创建自定义的JavaScript文件,用来存放需要被调用的JS函数,比如在wwwroot/js目录下创建site.js文件,内容如下:
// 定义简单的JS函数,返回问候语
function sayHello(name) {
return "Hello " + name + ", welcome to Blazor";
}
// 定义操作DOM的JS函数,修改指定元素的内容
function updateElementText(elementId, text) {
const element = document.getElementById(elementId);
if (element) {
element.innerText = text;
}
}
// 定义异步JS函数,模拟异步操作
function asyncJsFunction(delayMs) {
return new Promise(resolve => {
setTimeout(() => {
resolve("异步操作完成,延迟了" + delayMs + "毫秒");
}, delayMs);
});
}
然后在index.html(Blazor WebAssembly项目)或者_Host.cshtml(Blazor Server项目)的<head>或者<body>标签末尾引入这个JS文件:
<script src="js/site.js"></script>
基础调用方式
在Blazor组件中,通过注入IJSRuntime接口实例,就可以调用其中的InvokeAsync方法执行JavaScript函数。InvokeAsync方法的第一个参数是JavaScript函数的名称,后面的参数是传递给该函数的参数,返回值是JS函数的返回结果。
调用无参数JS函数
如果JS函数不需要参数,直接传入函数名即可,示例组件代码如下:
@page "/js-call-demo"
@inject IJSRuntime JSRuntime
<h3>Blazor调用JS函数示例</h3>
<button @onclick="CallNoParamJs">调用无参数JS函数</button>
<p>调用结果:@result</p>
@code {
private string result;
private async Task CallNoParamJs() {
// 调用JS中定义的全局函数,这里假设有一个无参数的testFunc函数
// result = await JSRuntime.InvokeAsync<string>("testFunc");
}
}
调用有参数JS函数
调用需要传递参数的JS函数时,把参数按顺序放在函数名后面即可,参数类型会自动进行转换,支持基本类型、对象、数组等:
@page "/js-call-demo"
@inject IJSRuntime JSRuntime
<h3>调用有参数JS函数</h3>
<input @bind="userName" placeholder="输入用户名" />
<button @onclick="CallParamJs">调用带参数JS函数</button>
<p>调用结果:@greeting</p>
@code {
private string userName;
private string greeting;
private async Task CallParamJs() {
if (!string.IsNullOrEmpty(userName)) {
// 传递字符串参数给sayHello函数
greeting = await JSRuntime.InvokeAsync<string>("sayHello", userName);
}
}
}
传递复杂参数
除了基本类型参数,还可以传递对象、数组等复杂类型,Blazor会自动将C#对象序列化为JSON传递给JavaScript,JS端可以直接使用这个对象。
比如定义一个C#的用户类:
public class UserInfo {
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
然后在JS中定义接收对象的函数:
function handleUser(user) {
return `用户信息:姓名${user.name},年龄${user.age},邮箱${user.email}`;
}
Blazor组件中调用:
@inject IJSRuntime JSRuntime
<button @onclick="CallObjectParamJs">传递对象参数调用JS</button>
<p>结果:@userInfoResult</p>
@code {
private string userInfoResult;
private async Task CallObjectParamJs() {
var user = new UserInfo {
Name = "张三",
Age = 25,
Email = "test@ipipp.com"
};
userInfoResult = await JSRuntime.InvokeAsync<string>("handleUser", user);
}
}
调用异步JavaScript函数
如果JavaScript函数返回的是Promise对象,也就是异步函数,Blazor的InvokeAsync方法会自动等待Promise完成,返回最终的结果,调用方式和同步函数一致:
@inject IJSRuntime JSRuntime
<button @onclick="CallAsyncJs">调用异步JS函数</button>
<p>异步结果:@asyncResult</p>
@code {
private string asyncResult;
private async Task CallAsyncJs() {
// 调用返回Promise的异步JS函数,等待结果返回
asyncResult = await JSRuntime.InvokeAsync<string>("asyncJsFunction", 1500);
}
}
注意事项
- JS函数必须是全局函数,或者挂载到window对象上的函数,否则Blazor无法找到对应的函数。
- Blazor Server项目中,JS互操作是通过SignalR连接实现的,所以调用会有一定的网络延迟,需要注意性能问题。
- 参数传递时,C#的DateTime类型会序列化为ISO格式的字符串,JS端如果需要处理时间需要做对应的转换。
- 不要在JS函数中返回DOM元素等无法序列化的对象,否则会导致调用失败。
常见场景示例:操作DOM元素
很多时候调用JS是为了操作DOM,比如修改元素样式、获取元素属性等,下面是修改指定元素文本的示例:
@inject IJSRuntime JSRuntime
<h3>操作DOM示例</h3>
<div id="targetDiv">原始文本内容</div>
<input @bind="newText" placeholder="输入新文本" />
<button @onclick="UpdateDivText">修改DIV内容</button>
@code {
private string newText;
private async Task UpdateDivText() {
if (!string.IsNullOrEmpty(newText)) {
await JSRuntime.InvokeAsync<object>("updateElementText", "targetDiv", newText);
}
}
}
这个示例中,通过调用之前定义的updateElementText函数,传入元素id和新的文本内容,就可以实现修改页面元素的功能,弥补了Blazor原生操作DOM不够灵活的不足。
BlazorJavaScriptJS互操作IJSRuntime修改时间:2026-07-16 15:15:40