罗马苏丹默罕默德

罗马苏丹默罕默德

BlazorServer中C#与JavaScript的相互调用

前言:

​ 虽然BlazorServer中推荐使用C#在razor页面中的替代JavaScript来完成逻辑的编写,但当需要使用第三方的javascript文件/组件里的内容时,则难免要在C#中调用其方法或对象反之当你的(用到第三方组件的)Javascript代码想要和后台交互时,则需要调用C#的代码。好在BlazorServer中这两种通信都是支持的。下面将介绍其具体的实现方式。

🌮一.C#调用JavaScript方法

🍎 BlazorServer启动时就已经创建了IJSRuntime的实例,所以你可以直接使用构造方法注入

public class CustomService
{
    private readonly IJSRuntime _runtime;

    public CustomService(IJSRuntime runtime)
    {
        _runtime = runtime;
    }
}

🍌在razor页面(组件)中也是直接获取即可

page "/mytest"
    
<!--直接使用@inject标签获取即可-->
@inject IJSRuntime runtime 

<h3>MyTest</h3>

1.调取公用函数

page "/mytest"
    
<!--直接使用@inject标签获取即可-->
@inject IJSRuntime runtime 

<h3>MyTest</h3>

<button type="button" @onclick="DoNothing">点击</button>

@code {

    public void DoNothing()
    {
        await runtime.InvokeVoidAsync("alert",new object[1] { "FUCKYOU" }); //无返回值
        //runtime.InvokeAsync<>();   有返回值
    }
}

测试结果:

BlazorServer中C#与JavaScript的相互调用-LMLPHP

2.调取外部JavaScript函数

上面的只单独调用公共函数的时候不多,大多数时候需要从别的地方获取。调用方法如下

现有一自定义js文件如下(TestScript.js)

function WhatTheHell() {
    alert("WTF");
}

function WhatTheHell_2() {
    alert("这次有返回值");
    return 123
}

function WhatTheHell_3(param) {
    alert("有返回值及参数");
    console.log(JSON.stringify(param));
    return 10086
}

先将其放到BlazorServer的js文件指定目录下(wwwroot/js/

BlazorServer中C#与JavaScript的相互调用-LMLPHP

再在_Host.cshtml中引入该js文件

BlazorServer中C#与JavaScript的相互调用-LMLPHP

在razor页面中使用

@page "/mytest"

@inject IJSRuntime runtime 

<h3>MyTest</h3>

<button type="button" @onclick="MethodOne">方法一(无返回值和参数)</button>  <br/>
<button type="button" @onclick="MethodTwo">方法二(无返回值)</button>    <br/>
<button type="button" @onclick="MethodThree">方法三(返回值和参数)</button> <br/>


@code {

    public async void MethodOne()
    {
        await runtime.InvokeVoidAsync("WhatTheHell",null);
    }

    public async void MethodTwo()
    {
        var num = await runtime.InvokeAsync<int>("WhatTheHell_2",null);
        Console.WriteLine("获取js的返回值为" + num);
    }
    public async void MethodThree()
    {
        var num =  await runtime.InvokeAsync<int>("WhatTheHell_3", new object[1] { "尼哥" });
        Console.WriteLine("获取js的返回值为" + num);
    }

}

测试结果为:

BlazorServer中C#与JavaScript的相互调用-LMLPHP

当JS的返回值为复杂对象时,则推荐使用IJSObjectReference来获取,具体可以参考

IJSObjectReference 接口 (Microsoft.JSInterop) | Microsoft Learn

🍕 二.JavaScript调用C#方法

在JavaScript中调用C#的方法则比较复杂,需要考虑到静态/动态区分的问题

🌀1.静态方法的调用

DotNet.invokeMethodAsync('AssemblyName', 'Namespace.ClassName', 'MethodName', arg1, arg2);

例:

@page "/jstest"

@inject IJSRuntime runtime

<h3>Jsusecsharp</h3>

<span style="font-size:36px">到达世界最高城 @Title</span>

<button type="button" @onclick="Change">前往朝圣</button>

@code {
    public static string Title = "沈阳!"; 

    public async void Change()
    {
        await runtime.InvokeVoidAsync("use_csharp",null);
    }

    [JSInvokable]
    public static void ChangeTheTitle()
    {
        Title = "理塘";
    }
}

js文件

async function use_csharp() {
    await DotNet.invokeMethodAsync('BlazorApp2','ChangeTheTitle', null);
}

测试结果:

BlazorServer中C#与JavaScript的相互调用-LMLPHP

✈️ 2…动态方法的调用

下面是微软文档的内容

若要从 JavaScript (JS) 调用实例 .NET 方法,请执行以下操作:

  • 通过将实例包装在 DotNetObjectReference 中并对其调用 Create,将 .NET 实例通过引用传递给 JS。

  • 使用传递的 DotNetObjectReference 中的 invokeMethodAsync(推荐)或 invokeMethod(仅限 Blazor WebAssembly)从 JS 调用 .NET 实例方法。 传入实例 .NET 方法的标识符以及任意自变量。 在从 JS 调用其他 .NET 方法时,也可以将 .NET 实例作为参数传递。

    如下示例中:

    • dotNetHelperDotNetObjectReference
    • {.NET METHOD ID} 占位符是 .NET 方法标识符。
    • {ARGUMENTS} 占位符是要传递给该方法的以逗号分隔的可选参数,其中每个参数都必须是可执行 JSON 序列化的。

⛵️ 总结:

动态方法的调用需要传递实例(使用DotNetObjectReference对象),需要在方法中设置实例参数,再由实例进行invoke操作。

例:

@page "/jstest"
@using BlazorApp2.Utils

@inject IJSRuntime runtime

<h3>Jsusecsharp</h3>

<span style="font-size:36px">到达世界最高城 @Title</span>

<button type="button" @onclick="Change">前往朝圣</button>

@code {
    public static string Title = "沈阳!";
	//用于传递给JS的实例
    private DotNetObjectReference<Jsusecsharp> objref;

    protected override void OnInitialized()
    {
        objref = DotNetObjectReference.Create(this);
    }

    public async void Change()
    {
        //将实例作为参数传给调用的JS
        await runtime.InvokeVoidAsync("use_csharp_dy",objref);
    }

    /// <summary>
    /// 静态方法
    /// </summary>
    [JSInvokable]
    public static void ChangeTheTitle()
    {
        Title = "理塘";
    }

    [JSInvokable("ChangeTheTitle_2")]
    public void ChangeTheTitle_2()
    {
        Title = "通辽";
    }


}

JS:

async function use_csharp_dy(instance) {
    //instance 即为razor中的objref,由其进行调用
    await instance.invokeMethodAsync('ChangeTheTitle_2', null);
    
}

参数结果:

BlazorServer中C#与JavaScript的相互调用-LMLPHP

未完。。。。。

08-24 10:41