ASP.NET Core Blazor WebAssembly 之 .NET JavaScript互调
<p>Blazor WebAssembly可以在浏览器上跑C#代码,但是很多时候显然还是需要跟JavaScript打交道。比如操作dom,当然跟angular、vue一样不提倡直接操作dom;比如浏览器的后退导航。反之JavaScript也有可能需要调用C#代码来实现一些功能,毕竟客户的需求是千变万化的,有的时候只能通过一些hack的手段来实现。</p><h2 id="net调用javascript函数">.NET调用JavaScript函数</h2>
<h3 id="使用jsruntimeinvokevoidasync调用无返回值的javascript函数">使用JSRuntime.InvokeVoidAsync调用无返回值的JavaScript函数</h3>
<p>显然我们的.NET类库里不会有JavaScript内置的alert方法来显示提示,这里演示下如何调用JavaScript的alert方法:</p>
<pre><code><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 .");
}
}
</code></pre>
<p><img src="https://s1.ax1x.com/2020/06/11/tqmG2F.gif" alt="" loading="lazy"></p>
<h3 id="使用jsruntimeinvokevoidasync调用具有返回值的javascript函数">使用JSRuntime.InvokeVoidAsync调用具有返回值的JavaScript函数</h3>
<p>我们在JavaScript环境定义一个加法函数然后.NET这边调用拿到结果:</p>
<pre><code> <script>
function add(a, b) {
return a + b;
}
</script>
</code></pre>
<blockquote>
<p>注意:JavaScript代码要放到wwwroot/index.html页面上里,不能直接放在组件里。</p>
</blockquote>
<p>组件代码:</p>
<pre><code><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();
}
}
</code></pre>
<p>运行一下:</p>
<p><img src="https://s1.ax1x.com/2020/06/12/tLBLt0.gif" alt="" loading="lazy"></p>
<h2 id="javascript调用net方法">JavaScript调用.NET方法</h2>
<h3 id="javascript调用net静态方法">JavaScript调用.NET静态方法</h3>
<p>JavaScript调用.NET静态方法比较简单,把静态方法加上,然后在JavaScript环境使用DotNet对象直接call就行:<br>
定义.NET静态方法:</p>
<pre><code>
public static string GetNow()
{
return DateTime.Now.ToString();
}
</code></pre>
<p>使用JavaScript调用GetNow:</p>
<pre><code>$(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
DotNet.invokeMethodAsync('BlazorWasmComponent', 'GetNow')
.then(data => {
alert(data);
});
})
}, 10000)
);
</code></pre>
<p>由于Blazor渲染UI结束后按钮才会插入到dom树上,所以这里使用一个傻办法让绑定事件的JavaScript代码置后运行。<br>
运行一下:<br>
<img src="https://s1.ax1x.com/2020/06/12/tLxZnO.gif" alt="" loading="lazy"></p>
<h3 id="javascript调用组件里的方法">JavaScript调用组件里的方法</h3>
<p>JavaScript调用组件里的方法比较绕,其实还是通过一个静态方法作为入口,把实例方法绑定一个静态delegate,然后让这个静态方法去执行delegate。<br>
.NET代码:</p>
<pre><code><h3>javascript call .net</h3>
<button id="btn1">
Js call .net
</button>
@inject IJSRuntime jsRuntime
@code {
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();
}
}
</code></pre>
<p>JavaScript代码:</p>
<pre><code> $(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
DotNet.invokeMethodAsync('BlazorWasmComponent', 'GetNow')
.then(data => {
alert(data);
});
})
}, 10000)
);
</code></pre>
<p>运行一下:<br>
<img src="https://s1.ax1x.com/2020/06/12/tLxZnO.gif" alt="" loading="lazy"></p>
<h3 id="调用对象的方法">调用对象的方法</h3>
<p>Blazor还可以把.NET对象(引用)直接传递到JavaScript运行时来让JavaScript直接调用.NET对象的方法。</p>
<p>总的来说大概分4步:</p>
<ol>
<li>实例化.net对象</li>
<li>DotNetObjectReference.Create方法把.NET对象包装</li>
<li>通过JSRuntime调用一个JavaScript方法把第二步生成的对象传递到JavaScript运行时</li>
<li>在JavaScript侧通过invokeMethodAsync方法调用.NET对象里的方法</li>
</ol>
<p>下面演示下把组件整个实例传递出去,然后调用里面的GetNowInInstance方法。</p>
<p>.net代码:</p>
<pre><code><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();
}
public string GetNowInInstance()
{
return DateTime.Now.ToString();
}
public void Dispose()
{
_objRef?.Dispose();
}
}
</code></pre>
<blockquote>
<p>注意:把.NET对象传递到JavaScript运行时存在内存泄漏的风险,所以组件需要实现IDisposable接口,在Dispose方法内调用objRef的Dispose方法来释放内存。</p>
</blockquote>
<p>JavaScript代码:</p>
<pre><code> var _netObj = null;
function receiveNetObj(obj) {
_netObj = obj;
}
$(document).ready(
setTimeout(() => {
$('#btn1').on('click', function () {
_netObj.invokeMethodAsync("GetNowInInstance").then(
r => alert(r)
);
})
}, 10000)
);
</code></pre>
<p>运行一下:<br>
<img src="https://s1.ax1x.com/2020/06/12/tLxZnO.gif" alt="" loading="lazy"></p>
<h2 id="总结">总结</h2>
<p>使用JSRuntime可以在.NET里调用JavaScript的方法,这些方法必须是全局的,也就是挂载在window对象上的。<br>
在JavaScript里调用.NET方法主要有两种:</p>
<ol>
<li>通过DotNet方式调用.NET的静态方法</li>
<li>把.NET对象直接传递到JavaScript运行时来调用对象上的方法</li>
</ol>
<p>相关内容</p>
<p>ASP.NET Core Blazor Webassembly 之 路由<br>
ASP.NET Core Blazor Webassembly 之 数据绑定<br>
ASP.NET Core Blazor Webassembly 之 组件<br>
ASP.NET Core Blazor 初探之 Blazor WebAssembly<br>
ASP.NET Core Blazor 初探之 Blazor Server</p>
<p>关注我的公众号一起玩转技术<br>
<img src="https://s1.ax1x.com/2020/06/29/NfQjds.jpg" alt="" loading="lazy"></p>
</div>
<div id="MySignature" role="contentinfo">
<div id="AllanboltSignature">
<p id="PSignature" style="border-top: #e0e0e0 1px dashed; border-right: #e0e0e0 1px dashed; border-bottom: #e0e0e0 1px dashed; border-left: #e0e0e0 1px dashed; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; font-family: 微软雅黑; font-size: 11px">
QQ群:1022985150 VX:kklldog 一起探讨学习.NET技术
<br>
作者:Agile.Zhou(kklldog)
<br>
出处:http://www.cnblogs.com/kklldog/
<br>本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
</p>
</div><br><br>
来源:https://www.cnblogs.com/kklldog/p/blazor-wasm-jsnetcall.html
頁:
[1]