侧边栏壁纸
博主头像
亿元丁真博主等级

行动起来,活在当下

  • 累计撰写 9 篇文章
  • 累计创建 8 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

BlazorServer中C#与JavaScript的相互调用

黎翰
2023-09-02 / 0 评论 / 0 点赞 / 52 阅读 / 11049 字

BlazorServer中C#与JavaScript的相互调用

前言:

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

🌮一.C#调用JavaScript方法

Blazor提供了IJSRuntime组件来提供与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<>();   有返回值
    }
}

测试结果:

test

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/

image-20230823154752547

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

image-20230823155052151

在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);
    }
​
}

测试结果为:

Gf2341

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

IJSObjectReference 接口 (Microsoft.JSInterop) | Microsoft Learn

🍕 二.JavaScript调用C#方法

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

🌀1.静态方法的调用

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

这将调用指定程序集(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);
}

测试结果:

Gf2342

✈️ 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);
    
}

参数结果:

Gf2346

未完。。。。。

0

评论区