Localização do JavaScript em aplicativos ASP.NET Core Blazor

Observação

Esta não é a versão mais recente deste artigo. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Aviso

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 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 informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.

Carregue o código JavaScript (JS) usando qualquer uma das seguintes abordagens:

Aviso

Coloque apenas uma tag <script> em um arquivo de componente (.razor), caso o componente tenha a garantia de adotar a SSR estática (renderização estática do lado do servidor) porque a tag <script> não pode ser atualizada de forma dinâmica.

Aviso

Não coloque uma marca <script> em um arquivo de componente (.razor) porque a marca <script> não pode ser atualizada dinamicamente.

Observação

Exemplos de documentação geralmente colocam scripts em uma marca <script> ou carregam scripts globais de arquivos externos. Essas abordagens poluem o cliente com funções globais. Para aplicativos de produção, recomendamos colocar JS em módulos JS separados que podem ser importados quando necessário. Para obter mais informações, consulte a seção Isolamento de JavaScript em módulos de JavaScript.

Observação

Exemplos de documentação colocam scripts em uma marca <script> ou carregam scripts globais de arquivos externos. Essas abordagens poluem o cliente com funções globais. A inserção JS em módulos JS separados que podem ser importados quando necessário não é suportada em Blazorversões anteriores ao ASP.NET Core 5.0. Se o aplicativo exigir o uso de módulos JS para isolamento de JS, recomendamos usar o ASP.NET Core 5.0 ou posterior para criar o aplicativo. Para obter mais informações, use a lista suspensa Versão para selecionar uma versão 5.0 ou posterior deste artigo e consulte a seção Isolamento de JavaScript em módulos JavaScript.

Carregar um script na marcação de <head>

A abordagem nesta seção não é geralmente recomendada.

Coloque as marcas de JavaScript (JS) (<script>...</script>) na <head>marcação do elemento:

<head>
    ...

    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</head>

O carregamento de JS do <head> não é a melhor abordagem pelos seguintes motivos:

  • A interoperabilidade de JS poderá falhar se o script depender de Blazor. É recomendável carregar os scripts usando uma das outras abordagens, não por meio da marcação de <head>.
  • A página poderá se tornar interativa mais lentamente devido ao tempo necessário para analisar o JS no script.

Carregar um script na marcação de <body>

Coloque as marcas JavaScript (<script>...</script>) dentro do elemento de fechamento </body> após a referência do script Blazor:

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script>
      window.jsMethod = (methodParameter) => {
        ...
      };
    </script>
</body>

No exemplo anterior, o espaço reservado {BLAZOR SCRIPT} é o caminho de script Blazor e o nome do arquivo. Para obter a localização do script, confira a estrutura do projeto ASP.NET Core Blazor.

Carregar um script de um arquivo JavaScript externo (.js) agrupado com um componente

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 void 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)
        {
            await module.DisposeAsync();
        }
    }
}

{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");

Para obter mais informações sobre RCLs, consulte Consumir componentes Razor do ASP.NET Core de uma RCL (biblioteca de classes) Razor.

Carregar um script de um arquivo JavaScript externo (.js)

Coloque as marcas de JavaScript (JS) (<script>...</script>) com um caminho de origem de script (src) dentro do elemento de </body>fechamento após a referência de script Blazor:

<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

Para os espaços reservados no exemplo anterior:

  • O espaço reservado {BLAZOR SCRIPT} é o caminho do script Blazor e o nome do arquivo. Para obter a localização do script, confira a estrutura do projeto ASP.NET Core Blazor.
  • O espaço reservado {SCRIPT PATH AND FILE NAME (.js)} é o caminho e o nome do arquivo de script em wwwroot.

No seguinte exemplo da marca <script> anterior, o arquivo scripts.js está na pasta wwwroot/js do aplicativo:

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

Você também pode fornecer scripts diretamente da pasta wwwroot se preferir não manter todos os scripts em uma pasta separada em wwwroot:

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

Quando o arquivo JS externo é fornecido por uma biblioteca de classes Razor, especifique o arquivo JS usando o caminho de ativo da Web estático estável: _content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}:

  • 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 {SCRIPT PATH AND FILE NAME (.js)} é o caminho e o nome do arquivo em wwwroot.
<body>
    ...

    <script src="{BLAZOR SCRIPT}"></script>
    <script src="_content/{PACKAGE ID}/{SCRIPT PATH AND FILE NAME (.js)}"></script>
</body>

No seguinte exemplo da marca <script> anterior:

  • A biblioteca de classes Razor tem um nome de assembly ComponentLibrary e um <PackageId> não é especificado no arquivo de projeto da biblioteca.
  • O arquivo scripts.js está na pasta wwwroot da biblioteca de classes.
<script src="_content/ComponentLibrary/scripts.js"></script>

Para obter mais informações, consulte Consumir componentes Razor do ASP.NET Core de uma RCL (biblioteca de classes) Razor.

Injetar um script antes ou após o início de Blazor

Para garantir que os scripts carreguem antes ou após o início de Blazor, use um inicializador JavaScript. Para obter mais informações e exemplos, veja Inicialização de Blazor no ASP.NET Core.

Injetar um script após o início de Blazor

Para injetar um script após a inicialização de Blazor, encadeie para o Promise que resulta de um início manual de Blazor. Para obter mais informações e um exemplo, veja Inicialização de Blazor no ASP.NET Core.

Isolamento de JavaScript em módulos JavaScript

Blazor ativa o isolamento do JavaScript (JS) em módulos JS padrão (especificação ECMAScript).

O isolamento de JS oferece os seguintes benefícios:

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

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

Há suporte para importação dinâmica com o import() operador com ASP.NET Core e Blazor:

if ({CONDITION}) import("/additionalModule.js");

No exemplo anterior, o espaço reservado {CONDITION} representa uma verificação condicional para determinar se o módulo deve ser carregado.

Para obter compatibilidade com o navegador, confira Posso usar: módulos JavaScript: importação dinâmica.