Compartilhar via


Consumir componentes Razor do ASP.NET Core de uma biblioteca de classes (RCL) Razor

Observação

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.

Importante

Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Para a versão atual, consulte a versão .NET 9 deste artigo.

Os componentes podem ser compartilhados em uma biblioteca de classes Razor(RCL) entre projetos. Inclua componentes e ativos estáticos em um aplicativo de:

  • Outro projeto na solução.
  • Uma biblioteca .NET de referência.
  • Um pacote NuGet.

Assim como os componentes são tipos regulares do .NET, os componentes fornecidos por uma RCL são assemblies .NET normais.

Criar uma RCL

  1. Criar um novo projeto.
  2. Na caixa de diálogo Criar um novo projeto, selecione Biblioteca de ClassesRazor na lista de modelos de projeto ASP.NET Core. Selecione Avançar.
  3. Na caixa de diálogo Configurar seu novo projeto, forneça um nome de projeto no campo Nome do projeto. Exemplos neste tópico usam o nome do projeto ComponentLibrary. Selecione Avançar.
  4. Na caixa de diálogo Informações adicionais, não selecione Páginas de suporte e exibições. Selecione Criar.
  5. Adicione a RCL a uma solução:
    1. Abrir a solução.
    2. No Gerenciador de Soluções, clique com o botão direito do mouse na solução. Selecione Adicionar>Projeto Existente.
    3. Navegue até o arquivo de projeto da RCL.
    4. Selecione o arquivo de projeto da RCL (.csproj).
  6. Adicione uma referência à RCL do aplicativo:
    1. Clique com o botão direito do mouse no aplicativo. Selecione Adicionar>Referência de projeto.
    2. Selecione o projeto da RCL. Selecione OK.

Consumo de um componente Razor de uma RCL

Para consumir componentes de uma RCL em outro projeto, use uma das seguintes abordagens:

  • Use o nome completo do tipo de componente, que inclui o namespace da RCL.
  • Componentes individuais podem ser adicionados pelo nome sem o namespace da RCL se a diretivaRazor da @using declara o namespace da RCL. Use uma das abordagens a seguir:
    • Adicionar a diretiva @using a componentes individuais.
    • incluir a diretiva @using no arquivo _Imports.razor de nível superior para disponibilizar os componentes da biblioteca para um projeto inteiro. Adicione a diretiva a um arquivo _Imports.razor em qualquer nível para aplicar o namespace a um único componente ou conjunto de componentes dentro de uma pasta. Quando um arquivo _Imports.razor é usado, componentes individuais não exigem uma diretiva @using para o namespace da RCL.

Nos exemplos a seguir, ComponentLibrary é uma RCL que contém o componente Component1. O componente Component1 é um componente de exemplo adicionado automaticamente a uma RCL criada com base no modelo de projeto RCL que não é criado para dar suporte a páginas e visualizações.

Component1.razor na RCL ComponentLibrary:

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

No aplicativo que consome a RCL, faça referência ao componente Component1 usando seu namespace, como mostra o exemplo a seguir.

ConsumeComponent1.razor:

@page "/consume-component-1"

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

<ComponentLibrary.Component1 />

Como alternativa, adicione uma diretiva @using e use o componente sem seu namespace. A diretiva @using a seguir também pode aparecer em qualquer arquivo _Imports.razor na pasta atual ou acima dela.

ConsumeComponent2.razor:

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

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

<Component1 />

Para componentes de biblioteca que usam isolamento de CSS, os estilos de componente são disponibilizados automaticamente para o aplicativo de consumo. Não é necessário vincular ou importar manualmente as folhas de estilos de componentes individuais da biblioteca ou seu arquivo CSS agrupado no aplicativo que consome a biblioteca. O aplicativo usa importações CSS para fazer referência aos estilos agrupados da RCL. Os estilos agrupados da RCL não serão publicados como um ativo da Web estático do aplicativo que consome os estilos. Para uma biblioteca de classes chamada ClassLib e um aplicativo Blazor com uma folha de estilos BlazorSample.styles.css, a folha de estilos da RCL é importada na parte superior da folha de estilos do aplicativo automaticamente no tempo de compilação:

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

Para os exemplos anteriores, a folha de estilos de Component1 (Component1.razor.css) é agrupada automaticamente.

Component1.razor.css na RCL de ComponentLibrary:

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

A imagem em segundo plano também está incluída no modelo de projeto RCL e fica na pasta wwwroot da RCL.

wwwroot/background.png na RCL de ComponentLibrary:

Imagem de fundo listrada diagonalmente do modelo de projeto RCL

Para fornecer estilos de componente de biblioteca adicionais de folhas de estilos na pasta wwwroot da biblioteca, adicione marcas <link> na folha de estilo ao consumidor da RCL, como mostra o próximo exemplo.

Importante

Em geral, os componentes da biblioteca usam o isolamento de CSS para agrupar e fornecer estilos de componente. Os estilos de componente que dependem do isolamento de CSS estão disponíveis automaticamente para o aplicativo que usa a RCL. Não é necessário vincular ou importar manualmente as folhas de estilos de componentes individuais da biblioteca ou seu arquivo CSS agrupado no aplicativo que consome a biblioteca. O exemplo a seguir mostra folhas de estilo globais fora do isolamento de CSS, o que geralmente não é um requisito para aplicativos típicos que consomem RCLs.

A imagem em segundo plano a seguir é usada no próximo exemplo. Se você implementar o exemplo mostrado nesta seção, clique com o botão direito do mouse na imagem para salvá-la localmente.

wwwroot/extra-background.png na RCL de ComponentLibrary:

Imagem de fundo listrada diagonalmente adicionada à biblioteca pelo desenvolvedor

Adicione uma nova folha de estilos à RCL com uma extra-style classe .

wwwroot/additionalStyles.css na RCL de ComponentLibrary:

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

Adicione um componente à RCL que usa a classe extra-style.

ExtraStyles.razor na RCL de ComponentLibrary:

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

Adicione uma página ao aplicativo que usa o componente ExtraStyles da RCL.

ConsumeComponent3.razor:

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

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

<ExtraStyles />

Link para a folha de estilos da biblioteca na marcação <head> do aplicativo (local do conteúdo <head>):

Blazor Web Apps:

<link href="@Assets["_content/ComponentLibrary/additionalStyles.css"]" rel="stylesheet">

Aplicativos Blazor WebAssembly autônomos:

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

Para componentes de biblioteca que usam isolamento de CSS, os estilos de componente são disponibilizados automaticamente para o aplicativo de consumo. Não é necessário vincular ou importar manualmente as folhas de estilos de componentes individuais da biblioteca ou seu arquivo CSS agrupado no aplicativo que consome a biblioteca. O aplicativo usa importações CSS para fazer referência aos estilos agrupados da RCL. Os estilos agrupados da RCL não serão publicados como um ativo da Web estático do aplicativo que consome os estilos. Para uma biblioteca de classes chamada ClassLib e um aplicativo Blazor com uma folha de estilos BlazorSample.styles.css, a folha de estilos da RCL é importada na parte superior da folha de estilos do aplicativo automaticamente no tempo de compilação:

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

Para os exemplos anteriores, a folha de estilos de Component1 (Component1.razor.css) é agrupada automaticamente.

Component1.razor.css na RCL de ComponentLibrary:

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

A imagem em segundo plano também está incluída no modelo de projeto RCL e fica na pasta wwwroot da RCL.

wwwroot/background.png na RCL de ComponentLibrary:

Imagem de fundo listrada diagonalmente do modelo de projeto RCL

A imagem em segundo plano e a folha de estilos a seguir são usadas pelo componente de exemplo Component1 da RCL. Não é necessário adicionar esses ativos estáticos a uma nova RCL criada a partir do modelo de projeto RCL, pois eles são adicionados automaticamente pelo modelo de projeto.

wwwroot/background.png na RCL de ComponentLibrary:

Imagem de fundo listrada diagonalmente adicionada à biblioteca pelo modelo de projeto RCL

wwwroot/styles.css na RCL de ComponentLibrary:

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

Para fornecer a classe CSS my-component de Component1, vincule-se à folha de estilos da biblioteca na marcação <head> do aplicativo (local do <head>conteúdo):

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

Disponibilizar componentes roteáveis na RCL

Para disponibilizar componentes roteáveis na RCL para solicitações diretas, o assembly da RCL deve ser divulgado para o roteador do aplicativo.

Abra o componente do aplicativo App (App.razor). Atribua uma coleção Assembly ao parâmetro AdditionalAssemblies do componente Router para incluir o assembly da RCL. No exemplo a seguir, o componente ComponentLibrary.Component1 é usado para descobrir o assembly da RCL.

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

Para obter mais informações, confira Roteamento e navegação do Blazor no ASP.NET Core.

Criação de uma RCL com ativos estáticos na pasta wwwroot

Os ativos estáticos de uma RCL estão disponíveis para qualquer aplicativo que consuma a biblioteca.

Coloque ativos estáticos na pasta wwwroot da RCL e faça referência aos ativos estáticos com o seguinte caminho no aplicativo: _content/{PACKAGE ID}/{PATH AND FILE NAME}. O espaço reservado {PACKAGE ID} é a ID do pacote da biblioteca. A ID do pacote terá como valor padrão o nome do assembly do projeto, se <PackageId> não for especificado no arquivo de projeto. O espaço reservado {PATH AND FILE NAME} é o caminho e o nome do arquivo em wwwroot. O formato de caminho também é usado no aplicativo para ativos estáticos fornecidos por um pacote NuGet adicionado à RCL.

O exemplo a seguir mostra o uso de ativos estáticos de RCL com uma RCL chamada ComponentLibrary e um aplicativo Blazor que consome a RCL. O aplicativo tem uma referência de projeto para a RCL ComponentLibrary.

A imagem do Jeep a® seguir é usada no exemplo desta seção. Se você implementar o exemplo mostrado nesta seção, clique com o botão direito do mouse na imagem para salvá-la localmente.

wwwroot/jeep-yj.png na RCL de ComponentLibrary:

Jeep YJ®

Adicione o componente JeepYJ a seguir à RCL.

JeepYJ.razor na RCL de ComponentLibrary:

<h3>ComponentLibrary.JeepYJ</h3>

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

Adicione o componente Jeep a seguir ao aplicativo que consome a RCL ComponentLibrary. O componente Jeep usa:

  • A imagem do Jeep YJ® da pasta ComponentLibrary da RCL wwwroot.
  • O componente JeepYJ da 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>

Componente Jeep renderizado:

Componente do Jeep

Para obter mais informações, consulte Interface do usuário reutilizávelRazor em bibliotecas de classes com ASP.NET Core.

Criação de uma RCL com arquivos JavaScript colocados com componentes

A colocação de arquivos JavaScript (JS) para componentes Razor é uma maneira conveniente de organizar scripts em um aplicativo.

Os componentes Razor de aplicativos Blazor colocam arquivos JS usando a extensão .razor.js e são endereçáveis publicamente usando o caminho para o arquivo no projeto:

{PATH}/{COMPONENT}.razor.js

  • O espaço reservado {PATH} é o caminho para o componente.
  • O espaço reservado {COMPONENT} é o componente.

Quando o aplicativo é publicado, a estrutura move automaticamente o script para a raiz da Web. Os scripts são movidos para bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{COMPONENT}.razor.js, onde estão os espaços reservados:

Nenhuma alteração é necessária para a URL relativa do script, pois Blazor cuida de colocar o arquivo JS em ativos estáticos publicados para você.

Esta seção e os exemplos a seguir se concentram principalmente em explicar a colocação de arquivos JS. O primeiro exemplo demonstra um arquivo colocado JS com uma função comum JS. O segundo exemplo demonstra a utilização de um módulo para carregar uma função, que é a abordagem recomendada para a maioria dos aplicativos de produção. Chamar JS a partir do .NET é totalmente abordado em Chamar funções JavaScript de métodos .NET no ASP.NET Core Blazor, em que há mais explicações sobre a API BlazorJS com exemplos adicionais. O descarte de componentes, que está presente no segundo exemplo, é abordado em Ciclo de vida do componente ASP.NET CoreRazor.

O componente JsCollocation1 a seguir carrega um script por meio de um componente HeadContent e chama uma função JS com IJSRuntime.InvokeAsync. O espaço reservado {PATH} é o caminho para o componente.

Importante

Se você usar o seguinte código para uma demonstração em um aplicativo de teste, altere o espaço reservado {PATH} para o caminho do componente (por exemplo: Components/Pages em .NET 8 ou posterior ou Pages em .NET 7 ou anterior). Em um Blazor Web App (.NET 8 ou mais recente), o componente requer um modo de renderização interativo aplicado ou globalmente ao aplicativo ou à definição do componente.

Adicione o script a seguir após o script Blazor (local do script inicial Blazor):

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

Componente 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 Task ShowPrompt()
    {
        result = await JS.InvokeAsync<string>(
            "showPrompt1", "What's your name?");
        StateHasChanged();
    }
}

O arquivo colocado JS é colocado ao lado do arquivo de componente JsCollocation1 com o nome do arquivo JsCollocation1.razor.js. No componente JsCollocation1, o script é referenciado no caminho do arquivo colocado. No exemplo a seguir, a função showPrompt1 aceita o nome do usuário de um Window prompt() e o retorna ao componente JsCollocation1 para exibição.

{PATH}/JsCollocation1.razor.js:

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

A abordagem anterior não é recomendada para uso geral em aplicativos de produção porque polui o cliente com funções globais. Uma abordagem melhor para aplicativos de produção é usar módulos JS. Os mesmos princípios gerais se aplicam ao carregamento de um módulo JS de um arquivo JS colocado, como o próximo exemplo demonstra.

O método OnAfterRenderAsync do componente JsCollocation2 a seguir carrega um módulo JS em module, que é uma classe de componente IJSObjectReference. module é usado para chamar a função showPrompt2. O espaço reservado {PATH} é o caminho para o componente.

Importante

Se você usar o seguinte código para uma demonstração em um aplicativo de teste, altere o espaço reservado {PATH} para o caminho do componente. Em um Blazor Web App (.NET 8 ou mais recente), o componente requer um modo de renderização interativo aplicado ou globalmente ao aplicativo ou à definição do componente.

Componente 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)
        {
            try
            {
                await module.DisposeAsync();
            }
            catch (JSDisconnectedException)
            {
            }
        }
    }
}

No exemplo anterior, JSDisconnectedException é preso durante o descarte do módulo caso Blazoro circuito seja SignalR perdido. Se o código anterior for usado em um Blazor WebAssembly aplicativo, não haverá conexão SignalR a perder, portanto, você poderá remover ocatch try-bloco e deixar a linha que descarta o módulo ().await module.DisposeAsync(); Para obter mais informações, confira Interoperabilidade ASP.NET Core Blazor JavaScript (interoperabilidade JS).

{PATH}/JsCollocation2.razor.js:

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

O uso de scripts e módulos para JS agrupados em uma biblioteca de classes de Razor (RCL) só tem suporte para JSmecanismo de interoperabilidade de Blazor com base na interface IJSRuntime. Se você estiver implementando a interop [JSImport]/[JSExport] JavaScript, consulte Interop JSImport/JSExport JavaScript com o ASP.NET Core Blazor.

Para scripts ou módulos fornecidos por uma biblioteca de classes (RCL) Razor, usando interop JS baseada emIJSRuntime, o seguinte caminho é usado:

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

  • O segmento de linha para o diretório atual (./) é necessário para criar o caminho de ativo estático correto para o arquivo JS.
  • O espaço reservado {PACKAGE ID} é o identificador do pacote da RCL (ou nome da biblioteca para uma biblioteca de classes referenciada pelo aplicativo).
  • O espaço reservado {PATH} é o caminho para o componente. Se um componente Razor estiver localizado na raiz da RCL, o segmento de linha não será incluído.
  • O espaço reservado {COMPONENT} é o nome do componente.
  • O espaço reservado {EXTENSION} corresponde à extensão do componente razor ou cshtml.

No seguinte exemplo de aplicativo Blazor:

  • O identificador do pacote da RCL é AppJS.
  • Os scripts de um módulo são carregados para o componente JsCollocation3 (JsCollocation3.razor).
  • O componente JsCollocation3 está na pasta Components/Pages da RCL.
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

Fornecer componentes e ativos estáticos para vários aplicativos Blazor hospedados

Para obter mais informações, confira Vários aplicativos Blazor WebAssembly do ASP.NET Core hospedados.

Analisador de compatibilidade de navegador do lado do cliente

Os aplicativos do lado do cliente têm como destino a área de superfície completa da API do .NET, mas nem todas as APIs do .NET têm suporte no WebAssembly devido a restrições de área restrita do navegador. APIs sem suporte geram PlatformNotSupportedException durante a execução no WebAssembly. Um analisador de compatibilidade de plataforma avisa o desenvolvedor quando o aplicativo usa APIs que não têm suporte nas plataformas de destino do aplicativo. Para aplicativos do lado do cliente, isso significa verificar se há suporte para APIs em navegadores. Os APIs da estrutura .NET para o analisador de compatibilidade é um processo em andamento, portanto, nem todas as APIs do .NET Framework estão anotadas no momento.

Blazor Web Apps que habilitam componentes webAssembly interativos, aplicativos Blazor WebAssembly e projetos RCL habilitam automaticamente as verificações de compatibilidade do navegador adicionando browser como uma plataforma compatível com o item MSBuild SupportedPlatform. Os desenvolvedores de biblioteca podem adicionar manualmente o item SupportedPlatform ao arquivo de projeto de uma biblioteca para habilitar o recurso:

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

Ao criar uma biblioteca, indique que uma API específica não tem suporte em navegadores especificando browser para UnsupportedOSPlatformAttribute:

using System.Runtime.Versioning;

...

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

Para obter mais informações, confira Anotar APIs como sem suporte em plataformas específicas (repositório do GitHub dotnet/designs.

Isolamento de JavaScript em módulos JavaScript

Blazor habilita o isolamento de JavaScript em módulos JavaScript padrão. O isolamento de JavaScript oferece os seguintes benefícios:

  • O JavaScript importado não polui mais o namespace global.
  • Os consumidores de uma biblioteca e componentes não precisam importar o JavaScript relacionado.

Para obter mais informações, consulte Chamar funções JavaScript de métodos .NET no ASP.NET Core Blazor.

Evite cortar os métodos do .NET que podem ser invocados por JavaScript

A nova vinculação de runtime corta os métodos do .NET que podem ser invocados pelo JavaScript da instância de classe, a menos que estejam explicitamente protegidos. Para obter mais informações, confira Chamar métodos do .NET das funções JavaScript no Blazor do ASP.NET Core.

Compilar, empacotar e enviar para o NuGet

Como as bibliotecas de classes Razor que contêm componentes Razor são bibliotecas .NET padrão, o empacotamento e envio para o NuGet não é diferente de empacotamento e envio de qualquer biblioteca para o NuGet. O empacotamento é executado usando o comando dotnet pack em um shell de comando:

dotnet pack

Carregue o pacote no NuGet usando o comando dotnet nuget push em um shell de comando.

Marcas comerciais

Jeep e Jeep YJ são marcas registradas da FCA US LLC (Stellantis NV).

Recursos adicionais