Взаимодействие ASP.NET Core Blazor с JavaScript (JS-взаимодействие)
Примечание.
Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.
Предупреждение
Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.
Внимание
Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.
В текущем выпуске см . версию .NET 8 этой статьи.
Приложение Blazor может вызывать функции JavaScript (JS) из методов .NET и методы .NET из функций JS. Такой подход называется взаимодействием с JavaScript (JS-взаимодействием).
Дополнительные сведения о JS-взаимодействии можно найти в следующих статьях:
- Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor
- Вызов методов .NET из функций JavaScript в Blazor ASP.NET Core
Примечание.
API взаимодействия JavaScript [JSImport]
/[JSExport]
доступен для клиентских компонентов в ASP.NET Core в .NET 7 или более поздней версии.
Дополнительные сведения см. в статье JavaScript JSImport/JSExport interop with ASP.NET Core Blazor.
Сжатие для интерактивных компонентов сервера с ненадежными данными
С помощью сжатия, который включен по умолчанию, избегайте создания безопасных (прошедших проверку подлинности или авторизованных) интерактивных компонентов на стороне сервера, отрисовывающих данные из ненадежных источников. Ненадежные источники включают параметры маршрута, строки запроса, данные из JS взаимодействия и любой другой источник данных, которые сторонний пользователь может контролировать (базы данных, внешние службы). Дополнительные сведения см. в руководстве ASP.NET Основных BlazorSignalR руководствах по устранению угроз и устранении угроз для ASP.NET интерактивной отрисовки на стороне сервера ASP.NET CoreBlazor.
Абстракции взаимодействия JavaScript и пакет функций
Пакет () (Microsoft.JSInterop
npmjs.com
пакет NuGet) предоставляет абстракции и функции взаимодействия между кодом .NET и JavaScript ().JS@microsoft/dotnet-js-interop
Справочный dotnet/aspnetcore
источник доступен в репозитории GitHub (/src/JSInterop
папка). Дополнительные сведения см. в файле репозитория README.md
GitHub.
Примечание.
По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Дополнительные ресурсы для написания JS скриптов взаимодействия в TypeScript:
- TypeScript
- Руководство. Создание приложения ASP.NET Core с помощью TypeScript в Visual Studio
- Управление пакетами npm в Visual Studio
Взаимодействие с DOM
Изменить DOM с помощью JavaScript (JS) можно только в том случае, если объект не взаимодействует Blazor. Blazor поддерживает представления модели DOM и взаимодействует с объектами DOM напрямую. Если элемент, отображаемый Blazor, изменяется извне с помощью JS напрямую или путем взаимодействия с JS, модель DOM может больше не соответствовать внутреннему представлению Blazor, что может привести к неопределенному поведению. Неопределенное поведение может просто мешать представлению элементов или их функций, а может и представлять угрозу безопасности для приложения или сервера.
Это руководство применяется не только к вашему коду взаимодействия JS, но и к любым библиотекам JS, используемым приложением, включая все, что предоставляется сторонней платформой, например Bootstrap JS и jQuery.
В некоторых примерах документации взаимодействие JS используется для изменения элемента исключительно для демонстрации как часть примера. В таких случаях в тексте появляется предупреждение.
Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
Класс JavaScript с полем функции типа
Класс JavaScript с полем функции типа не поддерживается взаимодействием BlazorJS . Используйте функции Javascript в классах.
Неподдерживаемый: GreetingHelpers.sayHello
в следующем классе как поле функции типа не обнаруживается с помощью BlazorJS функции взаимодействия и не может выполняться из кода C#:
export class GreetingHelpers {
sayHello = function() {
...
}
}
в следующем классе в качестве функции поддерживается:
export class GreetingHelpers {
sayHello() {
...
}
}
Также поддерживаются функции со стрелками:
export class GreetingHelpers {
sayHello = () => {
...
}
}
Избегайте встроенных обработчиков событий
Функцию JavaScript можно вызывать непосредственно из встроенного обработчика событий. В следующем примере используется функция JavaScript, alertUser
вызываемая при выборе кнопки пользователем:
<button onclick="alertUser">Click Me!</button>
Однако использование встроенных обработчиков событий является плохим вариантом проектирования для вызова функций JavaScript:
- Сочетание разметки HTML и кода JavaScript часто приводит к неуправляемому коду.
- Выполнение встроенного обработчика событий может быть заблокировано политикой безопасности содержимого (CSP) (документацией по MDN).
Рекомендуется избегать встроенных обработчиков событий в пользу подходов, которые назначают обработчики в JavaScript, addEventListener
как показано в следующем примере:
AlertUser.razor.js
:
export function alertUser() {
alert('The button was selected!');
}
export function addHandlers() {
const btn = document.getElementById("btn");
btn.addEventListener("click", alertUser);
}
AlertUser.razor
:
@page "/alert-user"
@implements IAsyncDisposable
@inject IJSRuntime JS
<h1>Alert User</h1>
<p>
<button id="btn">Click Me!</button>
</p>
@code {
private IJSObjectReference? module;
protected async override Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>("import",
"./Components/Pages/AlertUser.razor.js");
await module.InvokeVoidAsync("addHandlers");
}
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
await module.DisposeAsync();
}
}
}
Дополнительные сведения см. на следующих ресурсах:
- Расположение JavaScript в приложениях ASP.NET Core Blazor
- Общие сведения о событиях (документация по MDN)
Асинхронные вызовы JavaScript
JS Вызовы взаимодействия являются асинхронными, независимо от того, синхронный или асинхронный код. Вызовы являются асинхронными, чтобы обеспечить совместимость компонентов между серверными и клиентскими моделями отрисовки. При внедрении отрисовки на стороне сервера вызовы взаимодействия должны быть асинхронными, JS так как они отправляются через сетевое подключение. Для приложений, использующих исключительно отрисовку на стороне клиента, поддерживаются синхронные JS вызовы взаимодействия.
Дополнительные сведения см. в следующих статьях:
Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
Сериализация объектов
Blazor использует System.Text.Json для сериализации в соответствии с приведенными ниже требованиями и поведениями по умолчанию.
- Типы должны иметь конструктор по умолчанию, методы доступа
get
/set
должны быть общедоступными, а поля никогда не сериализуются. - Глобальная сериализация по умолчанию не настраивается во избежание повреждения существующих библиотек компонентов, негативного влияния на производительность и безопасность и снижения уровня надежности.
- Сериализация имен членов .NET приводит к именам ключей JSON в нижнем регистре.
- JSON десериализируется как JsonElement экземпляры C#, что позволяет использовать смешанный регистр. Внутреннее приведение свойств модели C# работает должным образом, несмотря на различия между именами ключей JSON и именами свойств C#.
- Сложные типы платформ, например KeyValuePair, могут быть обрезаны IL Trimmer при публикации и не присутствуют для JS взаимодействия. Рекомендуется создавать настраиваемые типы для типов, которые обрезает триммер IL.
- Blazorвсегда зависит от отражения сериализации JSON, в том числе при использовании создания источника C#.
false
ПриJsonSerializerIsReflectionEnabledByDefault
попытке сериализации параметр в файле проекта приложения приводит к ошибке.
Для пользовательской сериализации доступен API JsonConverter. Свойства могут быть помечены атрибутом [JsonConverter]
для переопределения сериализации по умолчанию для существующего типа данных.
Дополнительные сведения см. в ресурсах в документации по .NET:
- Сериализация и десериализация JSON (маршализация и отмена маршализации) в .NET
- Как настроить имена и значения свойств с помощью
System.Text.Json
- Как создавать пользовательские преобразователи для сериализации JSON (маршализация) в .NET
Blazor поддерживает оптимизированное взаимодействие с массивом байтов JS, которое позволяет избежать кодирования и декодирования массивов байтов в Base64. Приложение может применять пользовательскую сериализацию и передавать результирующие байты. Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
При быстрой сериализации большого объема объектов .NET либо в случае необходимости сериализации больших объектов .NET или значительного количества объектов .NET Blazor поддерживает демаршалированное взаимодействие с JS. Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.
Задачи очистки DOM во время удаления компонентов
Не выполняйте JS код взаимодействия для задач очистки DOM во время удаления компонентов. Вместо этого используйте MutationObserver
шаблон в JavaScript (JS) на клиенте по следующим причинам:
- Компонент, возможно, был удален из DOM по времени выполнения кода очистки
Dispose{Async}
. - Во время отрисовки Blazor на стороне сервера средство отрисовки может быть удалено платформой по времени выполнения кода очистки
Dispose{Async}
.
Шаблон MutationObserver
позволяет запускать функцию при удалении элемента из DOM.
В следующем примере DOMCleanup
компонент:
- Содержит объект
<div>
с числомid
cleanupDiv
. Элемент<div>
удаляется из DOM вместе с rest разметкой DOM компонента при удалении компонента из DOM. DOMCleanup
JS Загружает класс изDOMCleanup.razor.js
файла и вызывает ееcreateObserver
функцию для настройки обратногоMutationObserver
вызова. Эти задачи выполняются в методе жизненногоOnAfterRenderAsync
цикла.
DOMCleanup.razor
:
@page "/dom-cleanup"
@implements IAsyncDisposable
@inject IJSRuntime JS
<h1>DOM Cleanup Example</h1>
<div id="cleanupDiv"></div>
@code {
private IJSObjectReference? module;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
module = await JS.InvokeAsync<IJSObjectReference>(
"import", "./Components/Pages/DOMCleanup.razor.js");
await module.InvokeVoidAsync("DOMCleanup.createObserver");
}
}
async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
await module.DisposeAsync();
}
}
}
В следующем примере MutationObserver
обратный вызов выполняется при каждом изменении DOM. Выполните код очистки, когда if
инструкция подтверждает, что целевой элемент (cleanupDiv
) был удален (if (targetRemoved) { ... }
). Важно отключить и удалить MutationObserver
память после выполнения кода очистки.
DOMCleanup.razor.js
помещается параллельно с предыдущим DOMCleanup
компонентом:
export class DOMCleanup {
static observer;
static createObserver() {
const target = document.querySelector('#cleanupDiv');
this.observer = new MutationObserver(function (mutations) {
const targetRemoved = mutations.some(function (mutation) {
const nodes = Array.from(mutation.removedNodes);
return nodes.indexOf(target) !== -1;
});
if (targetRemoved) {
// Cleanup resources here
// ...
// Disconnect and delete MutationObserver
this.observer && this.observer.disconnect();
delete this.observer;
}
});
this.observer.observe(target.parentNode, { childList: true });
}
}
window.DOMCleanup = DOMCleanup;
Вызовы взаимодействия JavaScript без канала
Этот раздел применяется только к серверным приложениям.
Вызовы взаимодействия JavaScriptJS () не могут быть выданы после SignalR отключения канала. Без канала во время удаления компонентов или в любое другое время, когда канал не существует, следующий метод вызывает сбой и записывает сообщение о том, что канал отключен как:JSDisconnectedException
- JS Вызовы метода взаимодействия
Dispose
/DisposeAsync
вызовы для любого IJSObjectReference.
Чтобы избежать ведения журнала JSDisconnectedException или регистрации пользовательских сведений, перехватите исключение в инструкции try-catch
.
В следующем примере удаления компонентов:
- Компонент реализует IAsyncDisposable.
- Аргумент
objInstance
имеет тип IJSObjectReference. - JSDisconnectedException перехватываются и не регистрируются.
- Кроме того, вы можете записывать пользовательские сведения в инструкцию
catch
на любом выбранном уровне журнала. В следующем примере не регистрируется пользовательская информация, так как предполагается, что разработчик не заботится о том, когда или где каналы отключены во время удаления компонентов.
async ValueTask IAsyncDisposable.DisposeAsync()
{
try
{
if (objInstance is not null)
{
await objInstance.DisposeAsync();
}
}
catch (JSDisconnectedException)
{
}
}
Если вы должны очистить собственные JS объекты или выполнить другой JS код на клиенте после потери канала, используйте MutationObserver
шаблон в JS клиенте. Шаблон MutationObserver
позволяет запускать функцию при удалении элемента из DOM.
Дополнительные сведения см. в следующих статьях:
- Обработка ошибок в приложениях ASP.NET CoreBlazor. В разделе взаимодействия JavaScript рассматривается обработка ошибок в JS сценариях взаимодействия.
- ASP.NET жизненный цикл основных компонентов: удаление компонентов с
IDisposable
IAsyncDisposable
разделом описывает реализацию шаблонов удаления в Razor компонентах.Razor
Кэшированные файлы JavaScript
Файлы JavaScript (JS) и другие статические ресурсы обычно не кэшируются на клиентах во время разработки в среде Development
. Во время разработки запросы статических ресурсов содержат заголовок Cache-Control
со значением no-cache
или max-age
со значением, равным нулю (0
).
На этапе производства в среде Production
файлы JS обычно кэшируются клиентами.
Чтобы отключить кэширование на стороне клиента в браузерах, разработчики, как правило, используют один из следующих подходов:
- Отключение кэширования, когда открыта консоль средств разработчика браузера. Рекомендации см. в документации по средствам разработчика для каждого средства поддержки браузера:
- Обновление вручную в браузере любой веб-страницы приложения Blazor для перезагрузки файлов JS с сервера. ПО промежуточного слоя HTTP ASP.NET всегда учитывает допустимый некэшированный заголовок
Cache-Control
, отправляемый клиентом.
Дополнительные сведения см. в разделе:
Ограничения размера для вызовов взаимодействия с JavaScript
Этот раздел относится только к интерактивным компонентам в серверных приложениях. Для клиентских компонентов платформа не накладывает ограничение на размер входных и выходных данных JavaScript (JS).
Для интерактивных компонентов в серверных приложениях вызовы взаимодействия, передавающие данные от клиента на сервер, JS ограничены максимальным размером входящих SignalR сообщений, разрешенным для методов концентратора ( HubOptions.MaximumReceiveMessageSize по умолчанию: 32 КБ). Если размер сообщений SignalR (из JS в .NET) превышает MaximumReceiveMessageSize, возникает ошибка. Платформа не накладывает ограничение на размер сообщений SignalR от концентратора клиенту. Дополнительные сведения об ограничении размера, сообщениях об ошибках и рекомендациях по работе с ограничениями размера сообщений см . в ASP.NET основных BlazorSignalR руководствах.
Определение места выполнения приложения
Если это важно для приложения, чтобы узнать, где выполняется код для JS вызовов взаимодействия, используйте для OperatingSystem.IsBrowser определения, выполняется ли компонент в контексте браузера в WebAssembly.
ASP.NET Core