Blazor WebAssembly可以在瀏覽器上跑C#代碼,但是很多時候顯然還是需要跟JavaScript打交道,比如操作dom,當然跟angular、vue一樣不提倡直接操作dom;比如瀏覽器的后退導航,反之JavaScript也有可能需要呼叫C#代碼來實作一些功能,畢竟客戶的需求是千變萬化的,有的時候只能通過一些hack的手段來實作,
.NET呼叫JavaScript函式
使用JSRuntime.InvokeVoidAsync呼叫無回傳值的JavaScript函式
顯然我們的.NET類別庫里不會有JavaScript內置的alert方法來顯示提示,這里演示下如何呼叫JavaScript的alert方法:
<h3>.net call javascript</h3>
<button @onclick="CallJs">
Call alert
</button>
@inject IJSRuntime jsRuntime
@code {
private void CallJs()
{
jsRuntime.InvokeVoidAsync("alert", "this message from .net runtime .");
}
}

使用JSRuntime.InvokeVoidAsync呼叫具有回傳值的JavaScript函式
我們在JavaScript環境定義一個加法函式然后.NET這邊呼叫拿到結果:
<script>
function add(a, b) {
return a + b;
}
</script>
注意:JavaScript代碼要放到wwwroot/index.html頁面上里,不能直接放在組件里,
組件代碼:
<h3>.net call javascript</h3>
sum: @sum
<button @onclick="CallJs">
Call Add
</button>
@inject IJSRuntime jsRuntime
@code {
private int sum = 0;
private async void CallJs()
{
sum = await jsRuntime.InvokeAsync<int>("add", sum, 2);
this.StateHasChanged();
}
}
運行一下:

JavaScript呼叫.NET方法
JavaScript呼叫.NET靜態方法
JavaScript呼叫.NET靜態方法比較簡單,把靜態方法加上[JSInvokable],然后在JavaScript環境使用DotNet物件直接call就行:
定義.NET靜態方法:
[JSInvokable]
public static string GetNow()
{
return DateTime.Now.ToString();
}
使用JavaScript呼叫GetNow:
$(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
DotNet.invokeMethodAsync('BlazorWasmComponent', 'GetNow')
.then(data =https://www.cnblogs.com/kklldog/p/> {
alert(data);
});
})
}, 10000)
);
由于Blazor渲染UI結束后按鈕才會插入到dom樹上,所以這里使用一個傻辦法讓系結事件的JavaScript代碼置后運行,
運行一下:

JavaScript呼叫組件里的方法
JavaScript呼叫組件里的方法比較繞,其實還是通過一個靜態方法作為入口,把實體方法系結一個靜態delegate,然后讓這個靜態方法去執行delegate,
.NET代碼:
<h3>javascript call .net</h3>
<button id="btn1">
Js call .net
</button>
@inject IJSRuntime jsRuntime
@code {
[JSInvokable]
public static string GetNow()
{
return Act("");
}
public static Func<string, string> Act;
protected override void OnInitialized()
{
Act = GetNowInInstance;
base.OnInitialized();
}
public string GetNowInInstance(string str)
{
return DateTime.Now.ToString();
}
}
JavaScript代碼:
$(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
DotNet.invokeMethodAsync('BlazorWasmComponent', 'GetNow')
.then(data =https://www.cnblogs.com/kklldog/p/> {
alert(data);
});
})
}, 10000)
);
運行一下:

呼叫物件的方法
Blazor還可以把.NET物件(參考)直接傳遞到JavaScript運行時來讓JavaScript直接呼叫.NET物件的方法,
總的來說大概分4步:
- 實體化.net物件
- DotNetObjectReference.Create方法把.NET物件包裝
- 通過JSRuntime呼叫一個JavaScript方法把第二步生成的物件傳遞到JavaScript運行時
- 在JavaScript側通過invokeMethodAsync方法呼叫.NET物件里的方法
下面演示下把組件整個實體傳遞出去,然后呼叫里面的GetNowInInstance方法,
.net代碼:
<h3>javascript call .net</h3>
<button id="btn1">
Js call .net
</button>
@implements IDisposable
@inject IJSRuntime jsRuntime
@code {
IDisposable _objRef;
protected async override Task OnInitializedAsync()
{
_objRef = DotNetObjectReference.Create(this);
await jsRuntime.InvokeAsync<string>(
"receiveNetObj",
_objRef);
base.OnInitialized();
}
[JSInvokable]
public string GetNowInInstance()
{
return DateTime.Now.ToString();
}
public void Dispose()
{
_objRef?.Dispose();
}
}
注意:把.NET物件傳遞到JavaScript運行時存在記憶體泄漏的風險,所以組件需要實作IDisposable介面,在Dispose方法內呼叫objRef的Dispose方法來釋放記憶體,
JavaScript代碼:
var _netObj = null;
function receiveNetObj(obj) {
_netObj = obj;
}
$(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
_netObj.invokeMethodAsync("GetNowInInstance").then(
r => alert(r)
);
})
}, 10000)
);
運行一下:

總結
使用JSRuntime可以在.NET里呼叫JavaScript的方法,這些方法必須是全域的,也就是掛載在window物件上的,
在JavaScript里呼叫.NET方法主要有兩種:
- 通過DotNet方式呼叫.NET的靜態方法
- 把.NET物件直接傳遞到JavaScript運行時來呼叫物件上的方法
相關內容
ASP.NET Core Blazor Webassembly 之 路由
ASP.NET Core Blazor Webassembly 之 資料系結
ASP.NET Core Blazor Webassembly 之 組件
ASP.NET Core Blazor 初探之 Blazor WebAssembly
ASP.NET Core Blazor 初探之 Blazor Server
關注我的公眾號一起玩轉技術

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/13552.html
標籤:.NET Core
