Blazor如何调用JS方法,C#与JS互操作
Posted JimCarter
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Blazor如何调用JS方法,C#与JS互操作相关的知识,希望对你有一定的参考价值。
文章目录
1. 可放置javascript方法的位置
js方法可以在以下几个位置:
1.1 在head
里(不推荐)
<head>
<script>
window.jsMethod = (methodParameter) =>
...
;
</script>
</head>
为什么不推荐这么放:如果JS依赖于Blazor,那么互操作就会失败。而且也可能会导致页面响应变慢。
1.2 在body
里
<body>
<script src="_framework/blazor.webassembly|server.js"></script>
<script>
window.jsMethod = (methodParameter) =>
...
;
</script>
</body>
1.3 在Blazor启动之后注入js
首先将blazor.js
的autostart
设置为false
。然后调用Blaozr.start().then()
方法注入脚本。
<body>
<script src="_framework/blazor.webassembly|server.js"
autostart="false">
//设置为false
</script>
<script>
Blazor.start().then(function ()
var customScript = document.createElement('script');
customScript.setAttribute('src', 'scripts.js');
document.head.appendChild(customScript);
);
</script>
</body>
2. C#方法调用JS方法
可以使用IJSRuntime
对象调用js方法。主要有:
IJSRuntime.InvokeAsync
:第一个参数是js的方法名,是相对于全局来说(window
),如果要调用window.some.functionA
,则方法名就是some.functionA
。第二个参数是js方法的入参。JSRuntimeExtensions.InvokeVoidAsync
:当不需要js的返回值时,使用这个。
示例:
JS方法:
<script>
window.convertArray = (win1251Array) =>
var win1251decoder = new TextDecoder('windows-1251');
var bytes = new Uint8Array(win1251Array);
var decodedArray = win1251decoder.decode(bytes);
console.log(decodedArray);
return decodedArray;
;
</script>
C#方法:
@page "/test"
@inject IJSRuntime JS
@code
private async Task ConvertArray()
text = new(await JS.InvokeAsync<string>("convertArray", quoteArray));
3. JS方法调用C#方法
3.1 调用C#的静态方法
需要借助js的DotNet.invokeMethod
和DotNet.invokeMethodAsync
函数,第一个参数是程序集的名称,第二个参数是静态方法的名称(或别名),第三四等是静态方法的入参。
被调用的C#方法上要使用[JSInvokable]
特性。
JS方法:
returnArrayAsyncJs: function ()
DotNet.invokeMethodAsync('APP ASSEMBLY', 'DifferentMethodName','入参1','入参2')
.then(data =>
data.push(4);
console.log(data);
);
C#方法:
@code
[JSInvokable("DifferentMethodName")]
public static Task<int[]> ReturnArrayAsync(a,b)
return Task.FromResult(new int[] 1, 2, 3 );
3.2 调用C#的实例方法
以下例子来自微软文档,描述js如何调用HelloHelper
实例的SayHello
方法。
我看了一遍感觉有点脱裤子放屁:c#先调用了js,然后这个js又调用了hellohelper的sayhell。js没法直接new一个hellohelper所以需要用DotNetObjectReference.Create
。
- Razor页面:调用交互类
<button type="button" class="btn btn-primary" @onclick="TriggerNetInstanceMethod">点击</button>
@code
public async Task TriggerNetInstanceMethod()
//调用交互类
await new ExampleJsInterop(JS).CallHelloHelperSayHello("Blazor");
ExampleJsInterop.cs
交互类:调用JS代码
public class ExampleJsInterop : IDisposable
private readonly IJSRuntime js;
private DotNetObjectReference<HelloHelper> objRef;
public ExampleJsInterop(IJSRuntime js)
this.js = js;
public ValueTask<string> CallHelloHelperSayHello(string name)
objRef = DotNetObjectReference.Create(new HelloHelper(name));
//调用JS代码
return js.InvokeAsync<string>(
"exampleJsFunctions.sayHello",
objRef);
public void Dispose()
objRef?.Dispose();
- JS代码:拿到从交互类传过来的
HelloHelper
示例,并调用SayHello
方法
window.exampleJsFunctions =
sayHello: function (dotnetHelper)
return dotnetHelper.invokeMethodAsync('SayHello')
.then(r => console.log(r));
;
HelloHelper
类:
public class HelloHelper
public HelloHelper(string name)
Name = name;
public string Name get; set;
[JSInvokable]
public string SayHello() => $"Hello, Name!";
3.3 调用Razor组件的实例方法
类似于静态方法的调用,需要将要调用的实例方法包装成Action
。
JS代码,APP ASSEMBLY
是blazor程序集的名称:
function updateMessageCallerJS()
DotNet.invokeMethodAsync('APP ASSEMBLY', 'UpdateMessageCaller');
Razor组件:
@page "/JSInteropComponent"
@code
private static Action action;
private string message = "Select the button.";
protected override void OnInitialized()
action = UpdateMessage;
private void UpdateMessage()
//这个是需要调用的实例方法
message = "UpdateMessage Called!";
StateHasChanged();
[JSInvokable]
public static void UpdateMessageCaller()
action.Invoke();
3.3.1 调用组件实例方法的一个帮助类
这个帮助类在以下两种情况下比较有用,如果不用帮助类那么会影响到同一个组件的所有实例:
- 组件是一个类似于Item一样的可重用组件。
- 使用的是blazor server应用,导致多个用户使用的是同一个组件。
帮助类如下:
using System;
using Microsoft.JSInterop;
public class MessageUpdateInvokeHelper
private Action action;
public MessageUpdateInvokeHelper(Action action)
this.action = action;
[JSInvokable("APP ASSEMBLY")]
public void UpdateMessageCaller()
action.Invoke();
组件代码如下:
@inject IJSRuntime JS
<li>
@message
<button @onclick="InteropCall" style="display:@display">InteropCall</button>
</li>
@code
private string message = "Select one of these list item buttons.";
private string display = "inline-block";
private MessageUpdateInvokeHelper messageUpdateInvokeHelper;
protected override void OnInitialized()
messageUpdateInvokeHelper = new MessageUpdateInvokeHelper(UpdateMessage);
protected async Task InteropCall()
await JS.InvokeVoidAsync("updateMessageCallerJS",
DotNetObjectReference.Create(messageUpdateInvokeHelper));
private void UpdateMessage()
message = "UpdateMessage Called!";
display = "none";
StateHasChanged();
(每次new了一个新组件,也会new一个帮助类)
JS代码如下:
window.updateMessageCallerJS = (dotnetHelper) =>
dotnetHelper.invokeMethodAsync('APP ASSEMBLY', 'UpdateMessageCaller');
dotnetHelper.dispose();
以上是关于Blazor如何调用JS方法,C#与JS互操作的主要内容,如果未能解决你的问题,请参考以下文章