ASP.NET Core Blazor JavaScript met statische server-side rendering (SSR)
Notitie
Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.
Belangrijk
Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.
Zie de .NET 9-versie van dit artikelvoor de huidige release.
In dit artikel wordt uitgelegd hoe u JavaScript (JS) laadt in een Blazor Web App met statische server-side rendering (statische SSR) en verbeterde navigatie.
Sommige apps zijn afhankelijk van JS voor het uitvoeren van initialisatietaken die specifiek zijn voor elke pagina. Wanneer u de verbeterde navigatiefunctie van Blazorgebruikt, waardoor de gebruiker de hele pagina niet opnieuw kan laden, wordt paginaspecifieke JS mogelijk niet opnieuw uitgevoerd zoals verwacht telkens wanneer een uitgebreide paginanavigatie plaatsvindt.
Om dit probleem te voorkomen, wordt het afgeraden om te vertrouwen op paginaspecifieke <script>
elementen die buiten het indelingsbestand zijn geplaatst dat op het onderdeel is toegepast. In plaats daarvan moeten scripts een afterWebStarted
JS initialisatiefunctie registreren om initialisatielogica uit te voeren en een gebeurtenislistener te gebruiken om te luisteren naar pagina-updates die worden veroorzaakt door verbeterde navigatie.
Gebeurtenissen
In de volgende voorbeelden van gebeurtenisluisteraars is de tijdelijke aanduiding {CALLBACK}
de callback-functie.
Verbeterde navigatiestart (
enhancednavigationstart
) activeert een callback voordat er een verbeterde navigatie plaatsvindt:blazor.addEventListener("enhancednavigationstart", {CALLBACK});
Einde van verbeterde navigatie (
enhancednavigationend
) triggert een callback nadat een verbeterde navigatie heeft plaatsgevonden:blazor.addEventListener("enhancednavigationend", {CALLBACK});
Verbeterde belasting van navigatiepagina's (
enhancedload
) activeert een callback telkens wanneer de pagina wordt bijgewerkt vanwege een verbeterde navigatie, inclusief streaming-updates:blazor.addEventListener("enhancedload", {CALLBACK});
Om dit probleem te voorkomen, wordt het afgeraden om te vertrouwen op paginaspecifieke <script>
elementen die buiten het indelingsbestand zijn geplaatst dat op het onderdeel is toegepast. In plaats daarvan moeten scripts een afterWebStarted
JS initialisatiefunctie registreren om initialisatielogica uit te voeren en een gebeurtenislistener te gebruiken om te luisteren naar pagina-updates die worden veroorzaakt door verbeterde navigatie:
blazor.addEventListener("enhancedload", {CALLBACK});
In het voorgaande voorbeeld is de plaatsaanduiding {CALLBACK}
de callback-functie.
Verbeterd scriptvoorbeelden voor het laden van pagina's
In het volgende voorbeeld ziet u een manier om JS code te configureren die moet worden uitgevoerd wanneer een statisch gerenderde pagina met verbeterde navigatie in eerste instantie wordt geladen of bijgewerkt.
Het volgende PageWithScript
onderdeelvoorbeeld is een onderdeel in de app waarvoor scripts moeten worden uitgevoerd met statische SSR en verbeterde navigatie. Het volgende onderdeelvoorbeeld bevat een PageScript
onderdeel uit een Razor klassebibliotheek (RCL) die verderop in dit artikel aan de oplossing wordt toegevoegd.
Components/Pages/PageWithScript.razor
:
@page "/page-with-script"
@using BlazorPageScript
<PageTitle>Enhanced Load Script Example</PageTitle>
<PageScript Src="./Components/Pages/PageWithScript.razor.js" />
Welcome to my page.
Voeg in de Blazor Web Apphet volgende JS bestandtoe:
-
onLoad
wordt aangeroepen wanneer het script wordt toegevoegd aan de pagina. -
onUpdate
wordt aangeroepen wanneer het script nog steeds op de pagina bestaat na een verbeterde update. -
onDispose
wordt aangeroepen wanneer het script na een verbeterde update van de pagina wordt verwijderd.
Components/Pages/PageWithScript.razor.js
:
export function onLoad() {
console.log('Loaded');
}
export function onUpdate() {
console.log('Updated');
}
export function onDispose() {
console.log('Disposed');
}
Voeg in een Razor Klassebibliotheek (RCL) (de voorbeeld-RCL heet BlazorPageScript
), de volgende module toe. Dit is een JS initialisatiefunctie.
wwwroot/BlazorPageScript.lib.module.js
:
const pageScriptInfoBySrc = new Map();
function registerPageScriptElement(src) {
if (!src) {
throw new Error('Must provide a non-empty value for the "src" attribute.');
}
let pageScriptInfo = pageScriptInfoBySrc.get(src);
if (pageScriptInfo) {
pageScriptInfo.referenceCount++;
} else {
pageScriptInfo = { referenceCount: 1, module: null };
pageScriptInfoBySrc.set(src, pageScriptInfo);
initializePageScriptModule(src, pageScriptInfo);
}
}
function unregisterPageScriptElement(src) {
if (!src) {
return;
}
const pageScriptInfo = pageScriptInfoBySrc.get(src);
if (!pageScriptInfo) {
return;
}
pageScriptInfo.referenceCount--;
}
async function initializePageScriptModule(src, pageScriptInfo) {
if (src.startsWith("./")) {
src = new URL(src.substr(2), document.baseURI).toString();
}
const module = await import(src);
if (pageScriptInfo.referenceCount <= 0) {
return;
}
pageScriptInfo.module = module;
module.onLoad?.();
module.onUpdate?.();
}
function onEnhancedLoad() {
for (const [src, { module, referenceCount }] of pageScriptInfoBySrc) {
if (referenceCount <= 0) {
module?.onDispose?.();
pageScriptInfoBySrc.delete(src);
}
}
for (const { module } of pageScriptInfoBySrc.values()) {
module?.onUpdate?.();
}
}
export function afterWebStarted(blazor) {
customElements.define('page-script', class extends HTMLElement {
static observedAttributes = ['src'];
attributeChangedCallback(name, oldValue, newValue) {
if (name !== 'src') {
return;
}
this.src = newValue;
unregisterPageScriptElement(oldValue);
registerPageScriptElement(newValue);
}
disconnectedCallback() {
unregisterPageScriptElement(this.src);
}
});
blazor.addEventListener('enhancedload', onEnhancedLoad);
}
Voeg geen<script>
tag toe aan het hoofdonderdeel van de app, meestal de App
component, voor BlazorPageScript.lib.module.js
omdat de module in dit geval een JS initialisatiefunctie (afterWebStarted
)is.
JS initializers worden gedetecteerd en automatisch geladen door het Blazor framework.
Voeg in de RCL het volgende PageScript
-onderdeel toe.
PageScript.razor
:
<page-script src="@Src"></page-script>
@code {
[Parameter]
[EditorRequired]
public string Src { get; set; } = default!;
}
Het PageScript
onderdeel werkt normaal gesproken op het hoogste niveau van een pagina.
Als u het PageScript
onderdeel in de indeling van een app plaatst (bijvoorbeeld MainLayout.razor
), wat resulteert in een gedeelde PageScript
tussen pagina's die de indeling gebruiken, wordt het onderdeel alleen uitgevoerd onLoad
na een volledige pagina opnieuw laden en onUpdate
wanneer er een uitgebreide pagina-update plaatsvindt, inclusief verbeterde navigatie.
Als u dezelfde module opnieuw wilt gebruiken op meerdere pagina's, maar ervoor wilt zorgen dat de onLoad
en onDispose
callbacks worden aangeroepen bij elke paginawijziging, voegt u een querystring toe aan het einde van het script, zodat deze als een andere module wordt herkend. Een app kan de conventie volgen om de naam van het onderdeel als waarde van de querytekenreeks te gebruiken. In het volgende voorbeeld is de queryreeks 'counter
' omdat deze PageScript
componentverwijzing in een Counter
component is geplaatst. Dit is slechts een suggestie en u kunt elk queryreeksschema gebruiken dat u wilt gebruiken.
<PageScript Src="./Components/Pages/PageWithScript.razor.js?counter" />
Als u wijzigingen in specifieke DOM-elementen wilt controleren, gebruikt u het MutationObserver
patroon in JS op de client. Zie ASP.NET Core Blazor JavaScript-interoperabiliteit (JS interop)voor meer informatie.
Implementatie zonder een RCL te gebruiken
De benadering die in dit artikel wordt beschreven, kan rechtstreeks in een Blazor Web App worden geïmplementeerd zonder een Razor klassebibliotheek (RCL) te gebruiken door de assets van de RCL naar de app te verplaatsen. Het gebruik van een RCL is echter handig omdat de RCL kan worden verpakt in een NuGet-pakket voor gebruik door Blazor apps in een organisatie.
Als u de assets naar een Blazor Web Appverplaatst, moet u de naam van de module (BlazorPageScript.lib.module.js
) wijzigen zodat deze overeenkomt met de app volgens de regels voor bestandsnamen voor JS initialisatieprogramma's. Als het bestand niet juist is benoemd, kan Blazor de module niet detecteren en laden en wordt de gebeurtenis afterWebStarted
niet automatisch uitgevoerd wanneer de app wordt gestart.