Как использовать JavaScript в Blazor

Рейтинг: 1Ответов: 3Опубликовано: 28.02.2023

Я использую Blazor для создания клиентских веб-приложений и хочу интегрировать JavaScript для выполнения определённых задач, таких как работа с библиотеками JavaScript или манипуляции с DOM

Я пыталась добавить скрипт в проект, следуя примеру. Для этого я добавила следующий код в файл _Layout.cshtml, в секцию body после основного скрипта _framework:

<script src="js/myJsFile.js"></script>

Затем я создала скрипт myJsFile.js в папке wwwroot -> js. Однако мой скрипт не работает, и я не могу понять, что делаю неправильно

Подскажите, какие возможные способы интеграции JavaScript в Blazor существуют и как правильно добавить и использовать пользовательский скрипт? В документации об этом не так много информации

Ответы

▲ 1Принят

Всего мне известно 4 способа, после многих тестов, я думаю, что этот вариант стоит на втором месте. Он хорошо изолирован, и каждый скрипт отдельно загружается для каждой страницы при необходимости.

Можно создать изоляцию кода и управлять зависимостями в приложении, не используя обертку сервиса. Ниже представлен пример кода, иллюстрирующий это

@inject IJSRuntime JsRuntime // .razor

private IJSObjectReference _module; // .cs или .razor @code

protected override async Task OnInitializedAsync()
{
    _module = await JsRuntime.InvokeAsync<IJSObjectReference>("import", "./js/myJsFile.js"); 
}

public async Task MyFunction()
{
    if (_module != null)
    {
        await _module.InvokeVoidAsync("MyFunctionInMyJsFile"); // Вызов функции 
    }
}

// и не забыть dispose, чтобы избежать утечки памяти и освободить ресурсы 
public async ValueTask DisposeAsync()
{
    if (_module != null)
    {
        await _module.DisposeAsync();
        _module = null; 
    }
}

в myJsFile.js нужно экспортировать функцию, чтобы она была доступна из C#

export function MyFunctionInMyJsFile() {
    // do somethink
}
▲ 1

не рекомендую, но есть такой способ тоже

body

    <script src="_framework/blazor.webassembly.js" autostart="false"></script>
    <script>
        Blazor.start().then(function () {
            var customScript = document.createElement('script');
            customScript.setAttribute('src', 'test.js');
            document.head.appendChild(customScript);
        });
    </script>

Убедитесь, что ваш файл test.js находится в папке wwwroot. Пример содержимого файла test.js:

function testFunc() {
    var block = document.querySelector('.block');
    if (block) {
        block.style.color = 'blue'; // изменим цвет для примера
    }
}

.razor

<button onclick="testFunc()">Изменить цвет</button> 
<div class="block">Красный цвет</div>

Недостатки данного подхода

Поскольку Blazor.start() выполняется асинхронно, выполнение кода в test.js может начаться до полной загрузки приложения Blazor. Это может привести к тому, что функции в test.js не будут работать, если они зависят от элементов, созданных Blazor... Также источники не контролируются и открыты

▲ 0

Вот еще один рекомендуемый способ после способа IJSObjectReference

Усложним, создаем обертку сервис куда внедряем зависимость IJSRuntime и импортируем оттуда js

в этом примере сервис сам dispose, то разор страница не делает этого

public class JavaScriptService : IAsyncDisposable
{
    private readonly IJSRuntime _jsRuntime;
    private IJSObjectReference _module;

    public JavaScriptService(IJSRuntime jsRuntime)
    {
        _jsRuntime = jsRuntime;
    }

    public async Task MyJsForMyRazorPage()
    {
        _module = await _jsRuntime.InvokeAsync<IJSObjectReference>("import", "./js/myJsFile.js");
        await _module.InvokeVoidAsync("MyFunctionFromJs");
    }

    public async ValueTask DisposeAsync()
    {
        if (_module != null)
        {
            await _module.DisposeAsync();
            _module = null;
        }
    }
}

Program.cs

builder.Services.AddScoped<JavaScriptService>();

.razor

@page "/example"

@inject JavaScriptService JsService

<button @onclick="CallJavaScript">Call JavaScript</button>

@code {
    private async Task CallJavaScript()
    {
        await JsService.MyJsForMyRazorPage();
    }
}