Loading

Blazor笔记-JavaScript Interop(JS互调用)

更新记录

注意:非教程。纯笔记,日常查询用的。需要教程的小伙伴找几本书看看即可哈哈,有Vue基础的话非常快,概念都是通的。非工作需要不建议深入学习Blazor,深入Vue吧,用的多,哈哈。

完整目录地址:https://www.cnblogs.com/cqpanda/p/17596348.html

点击查看
2024年3月7日 发布。
2023年8月1日 迁移笔记到博客。

.NET to JavaScript(C#调用JS)

Calling JavaScript from .NET is pretty simple. There are two ways of doing that:
• Global JavaScript
• JavaScript Isolation

Global JavaScript (the old way)

to call the method from C#, we would call it using JSRuntime.

There are two different methods we can use to call JavaScript:
• InvokeVoidAsync, which calls JavaScript, but doesn’t expect a return value.
• InvokeAsync<T>, which calls JavaScript and expects a return value of type T.

实现:

@inject IJSRuntime js
async Task xxxx()
{
    await js.InvokeVoidAsync("函数名", 参数);
}

JavaScript Module Isolation

In .NET 5, we got a new way to add JavaScript using JavaScript Isolation, which is a much nicer way to call JavaScript. It doesn’t use global methods, and it doesn’t require us to refer to the JavaScript file.

This is awesome for component vendors and end users because JavaScript will be loaded when needed. It will only be loaded once (Blazor handles that for us), and we don’t need to add a reference to the JavaScript file, which makes it easier to start and use a library

需要调用的js

export function showConfirm(message) {
 return confirm(message);
}

注入JSRuntime服务

@inject IJSRuntime jsRuntime

在代码中使用

//js模块的引用
IJSObjectReference jsmodule;

//protected override async Task OnAfterRenderAsync
或者在事件中引入
private async Task<bool> ShouldDelete()
{
 //引入js模块
 jsmodule = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "/_content/Components/RazorComponents/xxxxx.js");

 //调用js模块内的函数
 return await jsmodule.InvokeAsync<bool> ("showConfirm", "Are you sure?");
}

Implement the IAsyncDisposable interface and dispose of the JavaScript module when the component is destroyed:

@implements IAsyncDisposable

@code {
    ...
    public async ValueTask DisposeAsync()
    {
        if(JSModule.IsValueCreated)
        {
            await JSModule.Value.DisposeAsync();
        }
    }
}

How to differentiate between standard JavaScript and JavaScript modules?

The syntax for using standard JavaScript and JavaScript modules is different.
For example, standard JavaScript uses global variables and functions,
while JavaScript modules use the import and export statements to define dependencies and expose functionality between files.
In addition, standard JavaScript code is executed in the global scope, while JavaScript modules have their own scope and can be imported and used in other modules.

JavaScript to .NET(JS调用C#)

There are three ways of doing a callback from JavaScript to .NET code:
• A static .NET method call
• An instance method call
• A component instance method call

从JS调用C#有两种方式,一种是调用静态方法,另外一种是调用实例方法,无论那种方式,C#中能被JS调用的函数都需要标注JSInvokable属性注解。

Static .NET method call

To call a .NET function from JavaScript, we can make the function static, and we also need to add the JSInvokable attribute to the method.

语法:

DotNet.invokeMethod("程序集的名称", "静态方法名称",参数1,…,参数n);

实例:
add a function such as this in the code section of a Razor component, or inside a class:

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

In the JavaScript file, we can call that function using the following code:

DotNet.invokeMethodAsync('BlazorWebAssemblySample', 'ReturnArrayAsync').then(data => {
 data.push(4);
 console.log(data);
 });

The DotNet object comes from the Blazor.js or blazor.server.js file.
BlazorWebAssemblySample is the name of the assembly, and ReturnArrayAsync is the name of the static .NET function

It is also possible to specify the name of the function in the JSInvokeable attribute if we don’t want it to be the same as the method name like this:

[JSInvokable("DifferentMethodName")]

It is returned as a promise in the JavaScript file that we are waiting for, and then (using the then perator) we continue with the execution, adding a 4 to the array and then outputting the values in the console.

把JS对象传送到.NET中
JS代码:

//创建JS引用
var jsObjectReference = DotNet.createJSObjectReference(window);
//映射到.NET中的对象
DotNet.invokeMethodAsync('{ASSEMBLY NAME}', 'ReceiveWindowObject', jsObjectReference);
//释放JS引用
DotNet.disposeJSObjectReference(jsObjectReference);

C#代码:

//在C#中使用JS的对象
[JSInvokable]
public static void ReceiveWindowObject(IJSObjectReference objRef)
{
    ...
}

Instance method call

步骤:
1.把实例对象的引用先传到前端
2.用实例对象的引用来执行方法

将方法所在类的实例(可以是组件实例,可以是其他类的实例)的引用传递到JS中。

//如果是在组件中,获得组件的实例引用
DotNetObjectReference.Create(this);
//如是其他类型
var cInstance = new SomClass();
DotNetObjectReference.Create(cInstance)


//然后传给JS前端
@inject IJSRuntime jsRuntime

protected override async void OnInitialized()
{
    //把对象实例传递到JS前端
    await js.InvokeAsync(string)("DuiYinJSDeMethod",DotNetObjectReference.Create(this))
}

//需要被JS调用的方法
[JSInvokable]
public void DoSomething(object o)
{
    //将o转为需要的类型使用
}

JS前端:

var instacne;
function DuiYinJSDeMethod(o)
{
    o.invokeMethodAsync("DoSomething",instacne);
}

实例:
后端.NET代码:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    //获得组件的实例引用
    DotNetObjectReference.Create(this);

    //实例传给前端
    await js.InvokeAsync<string>("DuiYinJSDeMethod", DotNetObjectReference.Create(this));

    base.OnAfterRenderAsync(firstRender);
}

//JS前端需要调用的方法
[JSInvokable]
public string PP(string arg)
{
    return "abc" + arg;
}

前端JS代码:

<script>
    function DuiYinJSDeMethod(instanceReference)
    {
        //参数就是.NET对象的实例
        console.log(instanceReference);
        //调用.NET的方法
        var result = instanceReference.invokeMethodAsync("PP", "123");
        //获得结果
        result.then((data)=>{
            console.log(data);
        });
    }
</script>

Implementing an existing JavaScript library

相对于用上面的2种方法来封装JS库

posted @ 2024-03-07 15:27  重庆熊猫  阅读(19)  评论(0编辑  收藏  举报