Dela via


Consume ASP.NET Core Razor components from a Razor class library (RCL)

Note

Det här är inte den senaste versionen av den här artikeln. For the current release, see the .NET 9 version of this article.

Warning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. For the current release, see the .NET 9 version of this article.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

For the current release, see the .NET 9 version of this article.

Komponenter kan delas i ett Razor klassbibliotek (RCL) mellan projekt. Inkludera komponenter och statiska tillgångar i en app från:

  • Ett annat projekt i -lösningen.
  • Ett refererat .NET-bibliotek.
  • Ett NuGet-paket.

Precis som komponenter är vanliga .NET-typer är komponenter som tillhandahålls av en RCL normala .NET-sammansättningar.

Skapa en RCL

  1. Skapa ett nytt projekt.
  2. I dialogrutan Skapa ett nytt projekt väljer du Razor klassbibliotek i listan över ASP.NET Core-projektmallar. Välj Nästa.
  3. I dialogrutan Konfigurera ditt nya projekt anger du ett projektnamn i fältet Projektnamn. Exempel i det här avsnittet använder projektnamnet ComponentLibrary. Välj Nästa.
  4. In the Additional information dialog, don't select Support pages and views. Välj Skapa.
  5. Lägg till RCL i en lösning:
    1. Öppna lösningen.
    2. Högerklicka på lösningen i Solution Explorer. Välj Lägg till>befintligt projekt.
    3. Navigera till RCL:s projektfil.
    4. Välj RCL:s projektfil (.csproj).
  6. Lägg till en referens till RCL:en från appen:
    1. Högerklicka på appprojektet. Välj Lägg till>projektreferens.
    2. Välj RCL-projektet. Välj OK.

Consume a Razor component from an RCL

Om du vill använda komponenter från en RCL i ett annat projekt använder du någon av följande metoder:

  • Använd det fullständiga komponenttypnamnet, som innehåller RCL:s namnområde.
  • Enskilda komponenter kan läggas till med namn utan RCL:s namnområde om Razor@using-direktivet deklarerar RCL:s namnområde. Använd följande metoder:
    • Lägg till @using-direktivet i enskilda komponenter.
    • inkludera @using-direktivet i _Imports.razor-filen på den översta nivån för att göra bibliotekets komponenter tillgängliga för ett helt projekt. Lägg till direktivet i en _Imports.razor fil på valfri nivå för att tillämpa namnområdet på en enskild komponent eller uppsättning komponenter i en mapp. När en _Imports.razor fil används kräver enskilda komponenter inte ett @using direktiv för RCL:s namnområde.

I följande exempel är ComponentLibrary en RCL som innehåller komponenten Component1. Komponenten Component1 är en exempelkomponent som automatiskt läggs till i en RCL som skapats från RCL-projektmallen och som inte har skapats för att stödja sidor och vyer.

Component1.razor in the ComponentLibrary RCL:

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

I appen som använder RCL refererar du till den Component1 komponenten med dess namnområde, vilket visas i följande exempel.

ConsumeComponent1.razor:

@page "/consume-component-1"

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

<ComponentLibrary.Component1 />

Du kan också lägga till ett @using direktiv och använda komponenten utan dess namnområde. Följande @using-direktiv kan också visas i alla _Imports.razor filer i eller ovanför den aktuella mappen.

ConsumeComponent2.razor:

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

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

<Component1 />

För bibliotekskomponenter som använder CSS-isoleringgörs komponentformat automatiskt tillgängliga för den förbrukande appen. Du behöver inte länka eller importera bibliotekets enskilda komponentformatmallar manuellt eller dess paketerade CSS-fil i appen som använder biblioteket. Appen använder CSS-importer för att referera till RCL:s paketerade formatmallar. De paketerade formatmallarna publiceras inte som en statisk webbtillgång för appen som använder biblioteket. För ett klassbibliotek med namnet ClassLib och en Blazor app med en BlazorSample.styles.css formatmall importeras RCL:s formatmall längst upp i appens formatmall automatiskt vid byggtillfället:

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

För de föregående exemplen paketeras formatmallen Component1(Component1.razor.css) automatiskt.

Component1.razor.css in the ComponentLibrary RCL:

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

Bakgrundsbilden ingår också från RCL-projektmallen och finns i mappen wwwroot för RCL.

wwwroot/background.png in the ComponentLibrary RCL:

diagonalt randig bakgrundsbild från RCL-projektmallen

To provide additional library component styles from stylesheets in the library's wwwroot folder, add stylesheet <link> tags to the RCL's consumer, as the next example demonstrates.

Viktig

I allmänhet använder bibliotekskomponenter CSS-isolering för att paketera och tillhandahålla komponentstilar. Komponentformat som förlitar sig på CSS-isolering görs automatiskt tillgängliga för den app som använder RCL. Du behöver inte länka eller importera bibliotekets enskilda komponentformatmallar manuellt eller dess paketerade CSS-fil i appen som använder biblioteket. Följande exempel är för att tillhandahålla globala formatmallar utanför CSS-isolering, vilket vanligtvis inte är ett krav för typiska appar som använder RCL:er.

Följande bakgrundsbild används i nästa exempel. Om du implementerar exemplet som visas i det här avsnittet högerklickar du på bilden för att spara den lokalt.

wwwroot/extra-background.png in the ComponentLibrary RCL:

diagonalt randig bakgrundsbild som lagts till i biblioteket av utvecklaren

Lägg till en ny formatmall i RCL med en extra-style-klass.

wwwroot/additionalStyles.css in the ComponentLibrary RCL:

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

Lägg till en komponent i den RCL som använder klassen extra-style.

ExtraStyles.razor in the ComponentLibrary RCL:

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

Lägg till en sida i appen som använder komponenten ExtraStyles från RCL.

ConsumeComponent3.razor:

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

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

<ExtraStyles />

Link to the library's stylesheet in the app's <head> markup (location of <head> content):

Blazor Web Apps:

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

Fristående Blazor WebAssembly appar:

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

För bibliotekskomponenter som använder CSS-isoleringgörs komponentformat automatiskt tillgängliga för den förbrukande appen. Du behöver inte länka eller importera bibliotekets enskilda komponentformatmallar manuellt eller dess paketerade CSS-fil i appen som använder biblioteket. Appen använder CSS-importer för att referera till RCL:s paketerade formatmallar. De paketerade formatmallarna publiceras inte som en statisk webbtillgång för appen som använder biblioteket. För ett klassbibliotek med namnet ClassLib och en Blazor app med en BlazorSample.styles.css formatmall importeras RCL:s formatmall längst upp i appens formatmall automatiskt vid byggtillfället:

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

För de föregående exemplen paketeras formatmallen Component1(Component1.razor.css) automatiskt.

Component1.razor.css in the ComponentLibrary RCL:

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

Bakgrundsbilden ingår också från RCL-projektmallen och finns i mappen wwwroot för RCL.

wwwroot/background.png in the ComponentLibrary RCL:

diagonalt randig bakgrundsbild från RCL-projektmallen

Följande bakgrundsbild och formatmall används av RCL:s Component1 exempelkomponent. Du behöver inte lägga till dessa statiska tillgångar i en ny RCL som skapats från RCL-projektmallen, eftersom de läggs till automatiskt av projektmallen.

wwwroot/background.png in the ComponentLibrary RCL:

diagonalt randig bakgrundsbild som lagts till i biblioteket av RCL-projektmallen

wwwroot/styles.css in the ComponentLibrary RCL:

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

To provide Component1's my-component CSS class, link to the library's stylesheet in the app's <head> markup (location of <head> content):

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

Göra routningsbara komponenter tillgängliga från RCL

För att göra routningsbara komponenter i RCL tillgängliga för direkta begäranden måste RCL:s sammansättning lämnas ut till appens router.

Öppna appens App komponent (App.razor). Tilldela en Assembly-samling till parametern AdditionalAssemblies för komponenten Router som ska inkludera RCL:s sammansättning. I följande exempel används den ComponentLibrary.Component1 komponenten för att identifiera RCL-sammansättningen.

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

Mer information finns i ASP.NET Core Blazor routning och navigering.

Skapa en RCL med statiska tillgångar i mappen wwwroot

En RCL:s statiska tillgångar är tillgängliga för alla appar som använder biblioteket.

Placera statiska tillgångar i mappen wwwroot för RCL och referera till de statiska tillgångarna med följande sökväg i appen: _content/{PACKAGE ID}/{PATH AND FILE NAME}. Platshållaren {PACKAGE ID} är bibliotekets paket-ID. Paket-ID:t är som standard projektets sammansättningsnamn om <PackageId> inte anges i projektfilen. Platshållaren {PATH AND FILE NAME} är sökväg och filnamn under wwwroot. Det här sökvägsformatet används också i appen för statiska tillgångar som tillhandahålls av NuGet-paket som lagts till i RCL.

I följande exempel visas användningen av statiska RCL-tillgångar med en RCL med namnet ComponentLibrary och en Blazor app som använder RCL. Appen har en projektreferens för ComponentLibrary RCL.

Följande Jeep-avbildning® används i det här avsnittets exempel. Om du implementerar exemplet som visas i det här avsnittet högerklickar du på bilden för att spara den lokalt.

wwwroot/jeep-yj.png in the ComponentLibrary RCL:

Jeep YJ®

Lägg till följande JeepYJ komponent i RCL.

JeepYJ.razor in the ComponentLibrary RCL:

<h3>ComponentLibrary.JeepYJ</h3>

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

Lägg till följande Jeep komponent i appen som använder ComponentLibrary RCL. Komponenten Jeep använder:

  • The Jeep YJ® image from the ComponentLibrary RCL's wwwroot folder.
  • Komponenten JeepYJ från 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>

Renderad Jeep komponent:

Jeep-komponent

För mer information, se Återanvändbart Razor användargränssnitt i klassbibliotek med ASP.NET Core.

Skapa en RCL med JavaScript-filer som är sorterade med komponenter

Samplacering av JavaScript-filer (JS) för Razor-komponenter är ett bekvämt sätt att organisera skript i en app.

Razor-komponenter av Blazor-appar samlar JS-filer med hjälp av .razor.js-filändelsen och kan adresseras offentligt med hjälp av sökvägen till filen i projektet.

{PATH}/{COMPONENT}.razor.js

  • The {PATH} placeholder is the path to the component.
  • The {COMPONENT} placeholder is the component.

När appen publiceras flyttar ramverket automatiskt skriptet till webbroten. Skripten flyttas till bin/Release/{TARGET FRAMEWORK MONIKER}/publish/wwwroot/{PATH}/{COMPONENT}.razor.js, där platshållarna är:

Ingen ändring krävs för skriptets relativa URL eftersom Blazor tar hand om att placera JS-filen i publicerade statiska tillgångar åt dig.

Det här avsnittet och följande exempel fokuserar främst på att förklara JS filsamordning. Det första exemplet visar en samlad JS fil med en vanlig JS funktion. Det andra exemplet visar användningen av en modul för att läsa in en funktion, vilket är den rekommenderade metoden för de flesta produktionsappar. Calling JS from .NET is fully covered in Call JavaScript functions from .NET methods in ASP.NET Core Blazor, where there are further explanations of the BlazorJS API with additional examples. Komponenthantering, som finns i det andra exemplet, beskrivs i ASP.NET Core Razor komponenthantering.

Följande JsCollocation1 komponent läser in ett skript via en HeadContent komponent och anropar en JS-funktion med IJSRuntime.InvokeAsync. The {PATH} placeholder is the path to the component.

Viktig

Om du använder följande kod för en demonstration i en testapp ändrar du platshållaren {PATH} till komponentens sökväg (till exempel Components/Pages i .NET 8 eller senare eller Pages i .NET 7 eller tidigare). I en Blazor Web App (.NET 8 eller senare) kräver komponenten ett interaktivt återgivningsläge som tillämpas antingen globalt på appen eller på komponentdefinitionen.

Add the following script after the Blazor script (location of the Blazor start script):

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

JsCollocation1 component ({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();
    }
}

Den samplacerade JS-filen placeras bredvid komponentfilen JsCollocation1 med filnamnet JsCollocation1.razor.js. In the JsCollocation1 component, the script is referenced at the path of the collocated file. I följande exempel accepterar funktionen showPrompt1 användarens namn från en Window prompt() och returnerar det till JsCollocation1 komponenten för visning.

{PATH}/JsCollocation1.razor.js:

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

Föregående metod rekommenderas inte för allmän användning i produktionsappar eftersom metoden förorenar klienten med globala funktioner. En bättre metod för produktionsappar är att använda JS moduler. Samma allmänna principer gäller för inläsning av en JS modul från en sammanställd JS fil, vilket visas i nästa exempel.

Följande JsCollocation2 komponentens OnAfterRenderAsync-metod läser in en JS-modul i module, som är en IJSObjectReference av komponentklassen. module används för att anropa funktionen showPrompt2. The {PATH} placeholder is the path to the component.

Viktig

If you use the following code for a demonstration in a test app, change the {PATH} placeholder to the path of the component. I en Blazor Web App (.NET 8 eller senare) kräver komponenten ett interaktivt återgivningsläge som tillämpas antingen globalt på appen eller på komponentdefinitionen.

JsCollocation2 component ({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 Task 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)
            {
            }
        }
    }
}

In the preceding example, JSDisconnectedException is trapped during module disposal in case Blazor's SignalR circuit is lost. Om föregående kod används i en Blazor WebAssembly app finns det ingen SignalR anslutning att förlora, så du kan ta bort try-catch-blocket och lämna raden som avyttrar modulen (await module.DisposeAsync();). Mer information finns i ASP.NET Core Blazor JavaScript-samverkan (JS interop).

{PATH}/JsCollocation2.razor.js:

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

Viktig

Placera inte en <script> tagg för JsCollocation2.razor.js efter Blazor skriptet eftersom modulen läses in och cachelagras automatiskt när den dynamiska import() anropas.

Use of scripts and modules for collocated JS in a Razor class library (RCL) is only supported for Blazor's JS interop mechanism based on the IJSRuntime interface. If you're implementing JavaScript [JSImport]/[JSExport] interop, see JavaScript JSImport/JSExport interop with ASP.NET Core Blazor.

För skript eller moduler som tillhandahålls av ett Razor-klassbibliotek (RCL) med IJSRuntime-baserad JS interop används följande sökväg:

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

  • Sökvägssegmentet för den aktuella katalogen (./) krävs för att skapa rätt statisk tillgångssökväg till JS-filen.
  • Platshållaren {PACKAGE ID} är RCL:s paketidentifierare (eller biblioteksnamn för ett klassbibliotek som refereras av appen).
  • The {PATH} placeholder is the path to the component. Om en Razor komponent finns i roten för RCL inkluderas inte sökvägssegmentet.
  • Platshållaren {COMPONENT} är komponentnamnet.
  • The {EXTENSION} placeholder matches the extension of component, either razor or cshtml.

I det följande app-exemplet Blazor:

  • RCL:s paketidentifierare är AppJS.
  • Skript för en modul läses in för komponenten JsCollocation3 (JsCollocation3.razor).
  • Komponenten JsCollocation3 finns i mappen Components/Pages för RCL.
module = await JS.InvokeAsync<IJSObjectReference>("import", 
    "./_content/AppJS/Components/Pages/JsCollocation3.razor.js");

Leverera komponenter och statiska tillgångar till flera värdbaserade Blazor appar

Mer information finns i Flera värdbaserade ASP.NET Core Blazor WebAssembly-appar.

Kompatibilitetsanalys för webbläsare på klientsidan

Appar på klientsidan riktar sig mot hela .NET API-ytan, men inte alla .NET-API:er stöds på WebAssembly på grund av webbläsarens sandbox-begränsningar. API:er som inte stöds genererar PlatformNotSupportedException när de körs på WebAssembly. En plattformskompatibilitetsanalys varnar utvecklaren när appen använder API:er som inte stöds av appens målplattformar. För appar på klientsidan innebär det att kontrollera att API:er stöds i webbläsare. Att kommentera .NET Framework-API:er för kompatibilitetsanalysen är en pågående process, så inte alla .NET Framework-API:er kommenteras för närvarande.

Blazor Web Apps that enable Interactive WebAssembly components, Blazor WebAssembly apps, and RCL projects automatically enable browser compatibility checks by adding browser as a supported platform with the SupportedPlatform MSBuild item. Biblioteksutvecklare kan manuellt lägga till SupportedPlatform objekt i ett biblioteks projektfil för att aktivera funktionen:

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

När du redigerar ett bibliotek anger du att ett visst API inte stöds i webbläsare genom att ange browser till UnsupportedOSPlatformAttribute:

using System.Runtime.Versioning;

...

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

Mer information finns i Kommentera API:er som inte stöds på specifika plattformar (dotnet/designs GitHub-lagringsplats.

JavaScript-isolering i JavaScript-moduler

Blazor enables JavaScript isolation in standard JavaScript modules. JavaScript-isolering ger följande fördelar:

  • Importerad JavaScript förorenar inte längre det globala namnområdet.
  • Användare av biblioteket och komponenterna behöver inte importera det relaterade JavaScript manuellt.

Mer information finns i Anropa JavaScript-funktioner från .NET-metoder i ASP.NET Core Blazor.

Undvik att trimma JavaScript-anropande .NET-metoder

Runtime relinking trims class instance JavaScript-invokable .NET methods unless they're explicitly preserved. Mer information finns i Anropa .NET-metoder från JavaScript-funktioner i ASP.NET Core Blazor.

Skapa, packa och skicka till NuGet

Eftersom Razor klassbibliotek som innehåller Razor komponenter är standardbibliotek för .NET, skiljer sig paketering och leverans till NuGet inte från att packa och skicka bibliotek till NuGet. Packning utförs med kommandot dotnet pack i ett kommandogränssnitt:

dotnet pack

Ladda upp paketet till NuGet med kommandot dotnet nuget push i ett kommandogränssnitt.

Varumärken

Jeep och Jeep YJ är registrerade varumärken som tillhör FCA US LLC (Stellantis NV).

Ytterligare resurser