IJSRuntime – Demo Global JS & JS Module
Cover: gọi JavaScript từ Blazor bằng global function và ES module, nhận giá trị trả về, gọi async, và dispose module đúng cách.
1️⃣ Global JS – gọi hàm toàn cục từ window
Global Result: none
Cách này dùng khi hàm JavaScript được khai báo toàn cục
(ví dụ trong window hoặc file JS load trực tiếp vào page).
Xem code
Razor (Pages/IJSRuntimeDemo.razor)
<button class="btn btn-primary" @onclick="Global_ShowAlert">Alert</button>
<button class="btn btn-success" @onclick="Global_GetBrowserInfo">Get Browser Info</button>
<button class="btn btn-warning" @onclick="Global_GetCurrentTime">Get Current Time</button>
<p><b>Global Result:</b> @GlobalResult</p>
@code {
private string GlobalResult = "none";
private async Task Global_ShowAlert()
{
await JS.InvokeVoidAsync("blazorGlobal.showAlert", "Hello from Blazor (Global JS)");
GlobalResult = "✅ Alert đã được gọi";
}
private async Task Global_GetBrowserInfo()
{
GlobalResult = await JS.InvokeAsync<string>("blazorGlobal.getBrowserInfo");
}
private async Task Global_GetCurrentTime()
{
GlobalResult = await JS.InvokeAsync<string>("blazorGlobal.getCurrentTime");
}
}
JavaScript global (wwwroot/js/ijsruntime-global-demo.js)
window.blazorGlobal = {
showAlert: function (message) {
alert(message);
},
getBrowserInfo: function () {
return `UserAgent: ${navigator.userAgent}`;
},
getCurrentTime: function () {
return new Date().toLocaleTimeString();
}
};
2️⃣ JS Module – import module rồi gọi hàm
Module Ready: False
Module Result: none
Cách này dùng với file ES module. Đây là cách hiện đại hơn, gọn scope và dễ quản lý hơn so với global function.
Xem code
Razor (Pages/IJSRuntimeDemo.razor)
@inject IJSRuntime JS
@implements IAsyncDisposable
<button class="btn btn-dark" @onclick="Module_Init">Init Module</button>
<button class="btn btn-info text-white" @onclick="Module_AddNumbers">Add 10 + 20</button>
<button class="btn btn-secondary" @onclick="Module_FormatMessage">Format Message</button>
<button class="btn btn-outline-danger" @onclick="Module_Dispose">Dispose Module</button>
<p><b>Module Ready:</b> @ModuleReady</p>
<p><b>Module Result:</b> @ModuleResult</p>
@code {
private IJSObjectReference? _module;
private string ModuleResult = "none";
private bool ModuleReady = false;
private async Task EnsureModuleAsync()
{
if (_module is null)
{
_module = await JS.InvokeAsync<IJSObjectReference>(
"import",
"./js/ijsruntime-module-demo.js");
ModuleReady = true;
}
}
private async Task Module_Init()
{
await EnsureModuleAsync();
ModuleResult = "Module initialized";
}
private async Task Module_AddNumbers()
{
await EnsureModuleAsync();
var result = await _module!.InvokeAsync<int>("addNumbers", 10, 20);
ModuleResult = $"10 + 20 = {result}";
}
private async Task Module_FormatMessage()
{
await EnsureModuleAsync();
ModuleResult = await _module!.InvokeAsync<string>(
"formatMessage",
"Hello from Blazor Module");
}
private async Task Module_Dispose()
{
if (_module is not null)
{
await _module.DisposeAsync();
_module = null;
ModuleReady = false;
ModuleResult = "Module disposed";
}
}
public async ValueTask DisposeAsync()
{
if (_module is not null)
{
await _module.DisposeAsync();
}
}
}
JavaScript module (wwwroot/js/moduleInterop.js)
export function addNumbers(a, b) {
return a + b;
}
export function formatMessage(message) {
return `[Module] ${message} at ${new Date().toLocaleTimeString()}`;
}
3️⃣ So sánh nhanh: Global vs Module
- Global JS: gọi nhanh, phù hợp demo nhỏ hoặc code cũ, nhưng dễ làm ô nhiễm global scope.
- JS Module: hiện đại hơn, tách scope rõ ràng, dễ bảo trì và nên ưu tiên trong dự án lớn.
-
Khi dùng module, nhớ dispose
IJSObjectReferencenếu component có thể bị hủy nhiều lần.
4️⃣ JS gọi C# (JS → .NET)
Result: none
JavaScript có thể gọi trực tiếp method C# bằng [JSInvokable].
Xem code
Razor
<button @onclick="CallJsToInvokeDotNet">
JS gọi C#
</button>
<p><b>Result:</b> @DotNetResult</p>
C#
private string DotNetResult = "none";
private async Task CallJsToInvokeDotNet()
{
await JS.InvokeVoidAsync("blazorGlobal.callDotNet");
}
[JSInvokable]
public static string DotNetHello()
{
return "Hello from C#";
}
JavaScript
window.blazorGlobal.callDotNet = async function () {
const result = await DotNet.invokeMethodAsync(
'BlazorSample',
'DotNetHello'
);
alert(result);
}