Использование компонентов ASP.NET Core Razor из библиотеки классов (RCL) Razor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

Компоненты можно совместно использовать в проектах посредством библиотеки классов Razor. Добавить компоненты и статические ресурсы в приложение можно из:

  • другого проекта в решении;
  • связанной библиотеки .NET.
  • пакета NuGet;

Так же как компоненты являются обычными типами .NET, компоненты, предоставляемые RCL, представляют собой обычные сборки .NET.

Создание библиотеки RCL

  1. Создание проекта
  2. В диалоговом окне Создать проект выберите пункт Библиотека классов Razor в списке шаблонов проектов ASP.NET Core. Выберите Далее.
  3. В диалоговом окне Настроить новый проект укажите имя проекта в поле Имя проекта или оставьте имя проекта по умолчанию. В примерах в этой статье используется имя проекта ComponentLibrary. Нажмите кнопку создания.
  4. В диалоговом окне Создать библиотеку классов Razor щелкните Создать.
  5. Добавьте RCL в решение:
    1. Откройте решение.
    2. В Обозревателе решений щелкните решение правой кнопкой мыши. Выберите Добавить>Существующий проект.
    3. Перейдите к файлу проекта RCL.
    4. Выберите файл проекта RCL (.csproj).
  6. Добавьте ссылку на RCL из приложения:
    1. Щелкните проект приложения правой кнопкой мыши. Выберите Добавить>Ссылка на проект.
    2. Выберите проект RCL. Нажмите ОК.

Если при создании RCL на основе шаблона выбран пункт Support pages and views (Поддержка страниц и представлений), который позволяет поддерживать страницы и представления, сделайте следующее:

  • Добавьте файл _Imports.razor в корень созданного проекта RCL со следующим содержимым, чтобы начать разработку компонента Razor:

    @using Microsoft.AspNetCore.Components.Web
    
  • Добавьте в файл проекта элемент SupportedPlatform следующего содержания (.csproj):

    <ItemGroup>
      <SupportedPlatform Include="browser" />
    </ItemGroup>
    

    Дополнительные сведения об элементе SupportedPlatform см. в разделе анализатора совместимости с браузером на стороне клиента.

Если при создании библиотеки RCL на основе шаблона выбран пункт Support pages and views (Поддержка страниц и представлений), который позволяет поддерживать страницы и представления, добавьте в корень сгенерированного проекта RCL файл _Imports.razor со следующим содержимым, чтобы начать разработку компонента Razor:

@using Microsoft.AspNetCore.Components.Web

Использование компонента Razor из RCL

Чтобы использовать компоненты из RCL в другом проекте, рассмотрите один из следующих подходов:

  • Используйте полное имя типа компонента, включающее в себя пространство имен RCL.
  • Отдельные компоненты можно добавлять по имени без пространства имен RCL, если директива @usingRazor объявляет пространство имен RCL. Используйте следующие подходы:
    • Добавьте директиву @using в отдельные компоненты.
    • Чтобы сделать компоненты библиотеки доступными для всего проекта, включите директиву @using в файл _Imports.razor верхнего уровня. Чтобы применить пространство имен к одному компоненту или набору компонентов в папке, добавьте директиву в файл _Imports.razor на любом уровне. При использовании файла _Imports.razor отдельным компонентам не потребуется директива @using для пространства имен RCL.

В приведенном ниже примере ComponentLibrary — это библиотека компонентов RCL, содержащая компонент Component1. Компонент Component1 — это пример компонента, который автоматически добавляется в библиотеку RCL, созданную из шаблона проекта RCL, который не предназначен для поддержки страниц и представлений.

Примечание.

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

Component1.razor в RCL ComponentLibrary:

<div class="my-component">
    This component is defined in the <strong>ComponentLibrary</strong> package.
</div>

В приложении, которое использует RCL, необходимо сослаться на компонент Component1, используя его пространство имен, как показано в следующем примере.

ConsumeComponent1.razor:

@page "/consume-component-1"

<h1>Consume component (full namespace example)</h1>

<ComponentLibrary.Component1 />

Кроме того, добавьте директиву @using и используйте компонент без его пространства имен. Следующая директива @using также может отображаться в любом файле _Imports.razor в текущей папке или над ней.

ConsumeComponent2.razor:

@page "/consume-component-2"
@using ComponentLibrary

<h1>Consume component (<code>@@using</code> example)</h1>

<Component1 />

Для компонентов библиотеки, использующих изоляцию CSS, стили компонентов автоматически становятся доступными для используемого приложения. Не требуется вручную связывать или импортировать таблицы стилей отдельных компонентов библиотеки или объединенный файл CSS в приложении, использующем библиотеку. Приложение использует импорт CSS для ссылки на объединенные стили в RCL. Объединенные стили не публикуются как статический веб-ресурс приложения, использующего библиотеку. Для библиотеки классов с именем ClassLib и приложения Blazor с таблицей стилей BlazorSample.styles.css таблица стилей RCL автоматически импортируется в верхней части таблицы стилей приложения во время сборки:

@import '_content/ClassLib/ClassLib.bundle.scp.css';

В предыдущих примерах таблица стилей Component1 (Component1.razor.css) объединяется автоматически.

Component1.razor.css в RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

Фоновое изображение также добавляется из шаблона проекта RCL и находится в папке wwwroot RCL.

wwwroot/background.png в RCL ComponentLibrary:

Экран

Чтобы предоставить дополнительные стили компонентов библиотеки из таблиц стилей в папке библиотеки wwwroot, добавьте теги таблицы стилей <link> в объект-получатель RCL, как показано в следующем примере.

Внимание

Как правило, компоненты библиотеки используют изоляцию CSS для создания и предоставления пакетов стилей компонентов. Стили компонентов, использующие изоляцию CSS, автоматически становятся доступными для приложения, использующего RCL. Не требуется вручную связывать или импортировать таблицы стилей отдельных компонентов библиотеки или объединенный файл CSS в приложении, использующем библиотеку. В следующем примере рассматривается предоставление глобальных таблиц стилей за пределами изоляции CSS, что обычно не является обязательными для обычных приложений, использующих RCL.

Приведенное фоновое изображение используется в примере, предоставленном ниже. Если вы реализуете пример, показанный в этом разделе, щелкните правой кнопкой мыши изображение, чтобы сохранить его локально.

wwwroot/extra-background.png в RCL ComponentLibrary:

Экран

Добавьте новую таблицу стилей в RCL с помощью класса extra-style.

wwwroot/additionalStyles.css в RCL ComponentLibrary:

.extra-style {
    border: 2px dashed blue;
    padding: 1em;
    margin: 1em 0;
    background-image: url('extra-background.png');
}

Добавьте компонент в библиотеку RCL, использующую класс extra-style.

ExtraStyles.razor в RCL ComponentLibrary:

<div class="extra-style">
    <p>
        This component is defined in the <strong>ComponentLibrary</strong> package.
    </p>
</div>

Добавьте страницу в приложение, которое использует компонент ExtraStyles из RCL.

ConsumeComponent3.razor:

@page "/consume-component-3"
@using ComponentLibrary

<h1>Consume component (<code>additionalStyles.css</code> example)</h1>

<ExtraStyles />

Создайте ссылку на таблицу стилей библиотеки в разметке <head> приложения (расположение содержимого <head>).

<link href="_content/ComponentLibrary/additionalStyles.css" rel="stylesheet" />

Для компонентов библиотеки, использующих изоляцию CSS, стили компонентов автоматически становятся доступными для используемого приложения. Не требуется вручную связывать или импортировать таблицы стилей отдельных компонентов библиотеки или объединенный файл CSS в приложении, использующем библиотеку. Приложение использует импорт CSS для ссылки на объединенные стили в RCL. Объединенные стили не публикуются как статический веб-ресурс приложения, использующего библиотеку. Для библиотеки классов с именем ClassLib и приложения Blazor с таблицей стилей BlazorSample.styles.css таблица стилей RCL автоматически импортируется в верхней части таблицы стилей приложения во время сборки:

@import '_content/ClassLib/ClassLib.bundle.scp.css';

В предыдущих примерах таблица стилей Component1 (Component1.razor.css) объединяется автоматически.

Component1.razor.css в RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

Фоновое изображение также добавляется из шаблона проекта RCL и находится в папке wwwroot RCL.

wwwroot/background.png в RCL ComponentLibrary:

Экран

В примере компонента Component1 RCL используется следующие фоновое изображение и таблица стилей. Эти статические ресурсы не нужно добавлять в новую RCL, созданную из шаблона проекта RCL, поскольку они добавляются автоматически шаблоном проекта.

wwwroot/background.png в RCL ComponentLibrary:

Экран

wwwroot/styles.css в RCL ComponentLibrary:

.my-component {
    border: 2px dashed red;
    padding: 1em;
    margin: 1em 0;
    background-image: url('background.png');
}

Чтобы предоставить Component1my-component класс CSS, перейдите к таблице стилей библиотеки в разметке приложения <head> (расположение содержимого<head>):

<link href="_content/ComponentLibrary/styles.css" rel="stylesheet" />

Создание доступных для routable компонентов из RCL

Чтобы сделать маршрутизируемые компоненты в RCL доступными для прямых запросов, сборка RCL должна быть раскрыта маршрутизатору приложения.

Откройте компонент приложения App (App.razor). Assembly Назначьте коллекцию AdditionalAssemblies параметру Router компонента, чтобы включить сборку RCL. В следующем примере ComponentLibrary.Component1 компонент используется для обнаружения сборки RCL.

AdditionalAssemblies="new[] { typeof(ComponentLibrary.Component1).Assembly }"

Дополнительные сведения см. в статье Маршрутизация ASP.NET Core Blazor и навигация.

Создание библиотеки RCL со статическими ресурсами в папке wwwroot

Статические ресурсы RCL доступны любому приложению, использующему библиотеку.

Поместите статические ресурсы в папку wwwroot RCL и создайте ссылки на статические ресурсы, используя в приложении следующий путь: _content/{PACKAGE ID}/{PATH AND FILE NAME}. Заполнитель {PACKAGE ID} — это идентификатор пакета библиотеки. Идентификатор пакета по умолчанию имеет имя сборки проекта, если значение <PackageId> не указано в файле проекта. Заполнитель {PATH AND FILE NAME} — это путь и имя файла в разделе wwwroot. Этот формат пути также используется в приложении для статических ресурсов, предоставляемых пакетами NuGet, добавленными в RCL.

В следующем примере показано, как использовать статические ресурсы RCL с именем ComponentLibrary и приложение Blazor, которое использует RCL. Приложение содержит ссылку на проект для RCL ComponentLibrary.

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

wwwroot/jeep-yj.png в RCL ComponentLibrary:

Экран Jeep YJ®

Добавьте следующий компонент JeepYJ в RCL.

JeepYJ.razor в RCL ComponentLibrary:

<h3>ComponentLibrary.JeepYJ</h3>

<p>
    <img alt="Jeep YJ&reg;" src="_content/ComponentLibrary/jeep-yj.png" />
</p>

Добавьте следующий компонент Jeep в приложение, использующее RCL ComponentLibrary. Компонент Jeep использует:

  • Изображение Jeep YJ® из папки wwwroot RCL ComponentLibrary.
  • Компонент JeepYJ из RCL.

Jeep.razor:

@page "/jeep"
@using ComponentLibrary

<div style="float:left;margin-right:10px">
    <h3>Direct use</h3>

    <p>
        <img alt="Jeep YJ&reg;" src="_content/ComponentLibrary/jeep-yj.png" />
    </p>
</div>

<JeepYJ />

<p>
    <em>Jeep</em> and <em>Jeep YJ</em> are registered trademarks of 
    <a href="https://www.stellantis.com">FCA US LLC (Stellantis NV)</a>.
</p>

Преобразованный компонент Jeep:

Экран

Дополнительные сведения см. в статье Многоразовый интерфейс Razor в библиотеках классов в ASP.NET Core.

Создание RCL с файлами JavaScript, размещенными с компонентами

Совместное размещение файлов JavaScript (JS) для Razor компонентов — удобный способ упорядочивания скриптов в приложении.

RazorКомпоненты файлов сортировки JS приложений Blazor с помощью .razor.js расширения и общедоступны адресуются с помощью пути к файлу в проекте:

{PATH}/{COMPONENT}.razor.js

  • Заполнитель {PATH} — это путь к компоненту.
  • Заполнитель {COMPONENT} — это компонент.

При публикации приложения платформа автоматически перемещает скрипт в корневой каталог. Скрипты перемещаются bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{COMPONENT}.razor.jsв место, где заполнители:

  • {TARGET FRAMEWORK MONIKER} — это Moniker целевой платформы (TFM).
  • {PATH} — путь к компоненту.
  • {COMPONENT} — имя компонента.

Изменение не требуется для относительного URL-адреса скрипта, так как Blazor заботится о размещении JS файла в опубликованных статических ресурсах.

В этом разделе и приведенных ниже примерах основное внимание уделяется объяснению JS расположения файлов. В первом примере показан файл с сортировкой JS с обычной JS функцией. Второй пример демонстрирует использование модуля для загрузки функции, которая является рекомендуемой подходом для большинства рабочих приложений. Вызов JS из .NET полностью рассматривается в функциях Вызова JavaScript из методов .NET в ASP.NET Core Blazor, где существуют дополнительные объяснения BlazorJS API с дополнительными примерами. Удаление компонентов, которое представлено во втором примере, рассматривается в ASP.NET жизненном цикле основных Razor компонентов.

Следующий JsCollocation1 компонент загружает скрипт с помощью HeadContent компонента и вызывает JS функцию.IJSRuntime.InvokeAsync Заполнитель {PATH} — это путь к компоненту.

Внимание

Если вы используете следующий код для демонстрации в тестовом приложении, измените {PATH} заполнитель на путь компонента (например, Components/Pages в .NET 8 или более поздней версии или Pages в .NET 7 или более ранней версии). Blazor В веб-приложении (.NET 8 или более поздней версии) компоненту требуется интерактивный режим отрисовки, применяемый глобально к приложению или к определению компонента.

Добавьте следующий скрипт после Blazor скрипта (расположение скрипта Blazor запуска):

<script src="{PATH}/JsCollocation1.razor.js"></script>

Компонент JsCollocation1 ({PATH}/JsCollocation1.razor):

@page "/js-collocation-1"
@inject IJSRuntime JS

<PageTitle>JS Collocation 1</PageTitle>

<h1>JS Collocation Example 1</h1>

<button @onclick="ShowPrompt">Call showPrompt1</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private string? result;

    public async void ShowPrompt()
    {
        result = await JS.InvokeAsync<string>(
            "showPrompt1", "What's your name?");
        StateHasChanged();
    }
}

Файл с сортировкой JS помещается рядом с файлом JsCollocation1 компонента с именем JsCollocation1.razor.jsфайла. В компоненте JsCollocation1 скрипт ссылается на путь к файлу с сортировкой. В следующем примере showPrompt1 функция принимает имя пользователя из объекта Window prompt() и возвращает его компоненту JsCollocation1 для отображения.

{PATH}/JsCollocation1.razor.js:

function showPrompt1(message) {
  return prompt(message, 'Type your name here');
}

Предыдущий подход не рекомендуется использовать в рабочих приложениях, так как он загрязняет клиента глобальными функциями. Лучший подход для рабочих приложений — использовать JS модули. Те же общие принципы применяются к загрузке JS модуля из коллакуированного JS файла, как показано в следующем примере.

Метод следующего JsCollocation2 компонента OnAfterRenderAsync загружает JS модуль moduleв , который является классом IJSObjectReference компонента. module используется для вызова showPrompt2 функции. Заполнитель {PATH} — это путь к компоненту.

Внимание

Если вы используете следующий код для демонстрации в тестовом приложении, измените {PATH} заполнитель на путь компонента. Blazor В веб-приложении (.NET 8 или более поздней версии) компоненту требуется интерактивный режим отрисовки, применяемый глобально к приложению или к определению компонента.

Компонент JsCollocation2 ({PATH}/JsCollocation2.razor):

@page "/js-collocation-2"
@implements IAsyncDisposable
@inject IJSRuntime JS

<PageTitle>JS Collocation 2</PageTitle>

<h1>JS Collocation Example 2</h1>

<button @onclick="ShowPrompt">Call showPrompt2</button>

@if (!string.IsNullOrEmpty(result))
{
    <p>
        Hello @result!
    </p>
}

@code {
    private IJSObjectReference? module;
    private string? result;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            /*
                Change the {PATH} placeholder in the next line to the path of
                the collocated JS file in the app. Examples:

                ./Components/Pages/JsCollocation2.razor.js (.NET 8 or later)
                ./Pages/JsCollocation2.razor.js (.NET 7 or earlier)
            */
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./{PATH}/JsCollocation2.razor.js");
        }
    }

    public async void ShowPrompt()
    {
        if (module is not null)
        {
            result = await module.InvokeAsync<string>(
                "showPrompt2", "What's your name?");
            StateHasChanged();
        }
    }

    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
}

{PATH}/JsCollocation2.razor.js:

export function showPrompt2(message) {
  return prompt(message, 'Type your name here');
}

Для скриптов или модулей, предоставляемых библиотекой Razor классов (RCL), используется следующий путь:

_content/{PACKAGE ID}/{PATH}/{COMPONENT}.{EXTENSION}.js

  • Заполнитель {PACKAGE ID} — это идентификатор пакета RCL (или имя библиотеки для библиотеки классов, на которую ссылается приложение).
  • Заполнитель {PATH} — это путь к компоненту. Если компонент Razor находится в корне RCL, сегмент пути не включается.
  • Заполнитель {COMPONENT} — это имя компонента.
  • Заполнитель {EXTENSION} соответствует расширению компонента либо razorcshtml.

В следующем примере приложения Blazor:

  • Идентификатор пакета RCL — AppJS.
  • Скрипты модуля загружаются для компонента JsCollocation3 (JsCollocation3.razor).
  • Компонент JsCollocation3 находится в папке Components/Pages библиотеки RCL.
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

Предоставление компонентов и статических ресурсов нескольким размещенным приложениям Blazor

Дополнительные сведения см. в статье Несколько размещенных приложений Blazor WebAssembly ASP.NET Core.

Анализатор совместимости браузера на стороне клиента

Клиентские приложения предназначены для полной области поверхности API .NET, но не все API .NET поддерживаются в WebAssembly из-за ограничений песочницы браузера. При выполнении в WebAssembly неподдерживаемые API-интерфейсы вызывают PlatformNotSupportedException. Анализатор совместимости платформ предупреждает разработчика, когда приложение использует API-интерфейсы, которые не поддерживаются целевыми платформами приложения. Для клиентских приложений это означает, что проверка, которые API поддерживаются в браузерах. Добавление заметок к API-интерфейсам .NET Framework для анализатора совместимости является непрерывным процессом, поэтому в настоящее время снабжены заметками не все API-интерфейсы .NET Framework.

Blazorвеб-приложения, включающих компоненты, приложения и проекты RCL интерактивного веб-сайта, автоматически обеспечивают совместимость браузеров Blazor WebAssembly проверка, добавив browser в качестве поддерживаемой платформы SupportedPlatform элемент MSBuild. Разработчики библиотек могут вручную добавить элемент SupportedPlatform в файл проекта библиотеки, чтобы включить эту функцию:

<ItemGroup>
  <SupportedPlatform Include="browser" />
</ItemGroup>

При создании библиотеки укажите, что конкретный API не поддерживается в браузерах, задав для browser значение UnsupportedOSPlatformAttribute:

using System.Runtime.Versioning;

...

[UnsupportedOSPlatform("browser")]
private static string GetLoggingDirectory()
{
    ...
}

Дополнительные сведения см. в статье Об аннотировании API как неподдерживаемых на определенных платформах (dotnet/designs репозиторий GitHub).

Изоляция JavaScript в модулях JavaScript

Blazor реализует изоляцию JavaScript в стандартных модулях JavaScript. Изоляция JavaScript обеспечивает следующие преимущества:

  • Импортированный JavaScript больше не засоряет глобальное пространство имен.
  • Пользователям библиотеки и компонентов не требуется импортировать связанный код JavaScript вручную.

Дополнительные сведения см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

Избегайте обрезки вызываемых методов JavaScript .NET

При повторном связывании среды выполнения методы JavaScript, вызываемые JavaScript, выполняются повторно, если они не сохраняются явным образом. Дополнительные сведения см. в статье Вызов методов .NET из функций JavaScript в ASP.NET Core Blazor.

Сборка, упаковка и отправка в NuGet

Так как библиотеки классов Razor, которые содержат компоненты Razor, являются стандартными библиотеками .NET, их упаковка и передача в NuGet не отличается от упаковки и передачи в NuGet любых других библиотек. Их можно упаковать, выполнив в командной оболочке команду dotnet pack:

dotnet pack

Чтобы отправить пакет в NuGet, используйте команду dotnet nuget push в командной оболочке.

Товарные знаки

Jeep и Jeep YJ являются зарегистрированными товарными знаками FCA US LLC (Stellantis NV).

Дополнительные ресурсы