Megosztás a következőn keresztül:


ASP.NET Core Blazor JavaScript-együttműködés (JS interop)

Jegyzet

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Figyelmeztetés

A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. A jelenlegi kiadásért lásd a cikk .NET 9-es verzióját.

Egy Blazor-alkalmazás meghívhat JavaScript (JS) függvényeket .NET-metódusokból és .NET-metódusokat JS függvényekből. Ezeket a forgatókönyveket JavaScript együttműködési (JS interop) nevezzük.

További JS interop-útmutató az alábbi cikkekben található:

Jegyzet

A JavaScript [JSImport]/[JSExport] interop API a .NET 7-es vagy újabb verziójában elérhető ASP.NET Core ügyféloldali összetevőihez.

További információért lásd JavaScript JSImport/JSExport interop és ASP.NET Core Blazor.

Nem megbízható adatokkal rendelkező interaktív kiszolgálóösszetevők tömörítése

Az alapértelmezés szerint engedélyezett tömörítéssel ne hozzon létre biztonságos (hitelesített/engedélyezett) interaktív kiszolgálóoldali összetevőket, amelyek nem megbízható forrásokból renderelik az adatokat. A nem megbízható források közé tartoznak az útvonalparaméterek, a lekérdezési sztringek, az JS interopból származó adatok, valamint a külső felhasználók által szabályozható egyéb adatforrások (adatbázisok, külső szolgáltatások). További információért lásd: ASP.NET Core BlazorSignalR útmutató és ASP.NET Core veszélyforrások elhárítása Blazor interaktív kiszolgálóoldali rendereléshez.

JavaScript interop absztrakciók és szolgáltatások csomag

A @microsoft/dotnet-js-interop csomag (npmjs.com) (Microsoft.JSInterop NuGet-csomag) absztrakciókat és funkciókat biztosít a .NET és a JavaScript (JS) kód közötti együttműködéshez. A referenciaforrás a dotnet/aspnetcore GitHub-adattárban (/src/JSInterop mappában)érhető el. További információt a GitHub-adattár README.md fájljában talál.

Jegyzet

A .NET referenciaforrásra mutató dokumentációs hivatkozások általában betöltik az adattár alapértelmezett ágát, amely a .NET következő kiadásának aktuális fejlesztését jelöli. Egy adott kiadás címkéjének kiválasztásához használja az Ágak vagy címkék váltása legördülő listát. További információ: A ASP.NET Core-forráskód (dotnet/AspNetCore.Docs #26205) verziócímkéjének kiválasztása.

További források JS interop szkriptek TypeScriptben való írásához:

Interakció a DOM-tal

Csak akkor mutálja a DOM-et JavaScripttel (JS), ha az objektum nem kommunikál a Blazor. Blazor fenntartja a DOM-ábrázolásokat, és közvetlenül kommunikál a DOM-objektumokkal. Ha a Blazor által renderelt elemet külsőleg, közvetlenül vagy JSJS Interop használatával módosítják, a DOM többé nem felel meg Blazorbelső ábrázolásának, ami meghatározatlan viselkedést eredményezhet. A nem definiált viselkedés csupán zavarhatja az elemek vagy azok funkcióinak megjelenítését, de biztonsági kockázatokat is jelenthet az alkalmazás vagy a kiszolgáló számára.

Ez az útmutató nem csak a saját JS interop-kódra vonatkozik, hanem az alkalmazás által használt JS kódtárakra is, beleértve a külső keretrendszerek által biztosított összes elemet, például Bootstrap JS és jQuery.

Néhány dokumentációs példában JS interop egy olyan elem mutációjára szolgál, pusztán szemléltetés céljából egy példa részeként. Ezekben az esetekben figyelmeztetés jelenik meg a szövegben.

További információ: JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor.

JavaScript-osztály, amelynek egy mezője függvény típusú

A típusfüggvényeket tartalmazó JavaScript-osztályokat BlazorJS interop nem támogatja. Javascript-függvények használata osztályokban.

Nem támogatott: az alábbi osztályban található, típusfüggvényként megadottGreetingHelpers.sayHello elemet a BlazorJS interopja nem deríti fel, ezért nem hajtható végre C# kódból:

export class GreetingHelpers {
  sayHello = function() {
    ...
  }
}

: az alábbi osztályban aGreetingHelpers.sayHello függvényként támogatott:

export class GreetingHelpers {
  sayHello() {
    ...
  }
}

A nyílfüggvények is elérhetőek:

export class GreetingHelpers {
  sayHello = () => {
    ...
  }
}

A beágyazott eseménykezelők elkerülése

A JavaScript-függvényt közvetlenül egy inline eseménykezelőből lehet meghívni. Az alábbi példában alertUser egy JavaScript-függvény, amelyet akkor hívunk meg, amikor a felhasználó kiválasztja a gombot:

<button onclick="alertUser">Click Me!</button>

A beágyazott eseménykezelők használata azonban nem megfelelő tervezési JavaScript-függvények meghívásához:

Javasoljuk, hogy kerülje a beágyazott eseménykezelőket, és részesítse előnyben azokat a megközelítéseket, amelyek kezelőket rendelnek a JavaScripthez addEventListener, ahogy az alábbi példa mutatja:

AlertUser.razor.js:

export function alertUser() {
  alert('The button was selected!');
}

export function addHandlers() {
  const btn = document.getElementById("btn");
  btn.addEventListener("click", alertUser);
}

AlertUser.razor:

@page "/alert-user"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>Alert User</h1>

<p>
    <button id="btn">Click Me!</button>
</p>

@code {
    private IJSObjectReference? module;

    protected async override Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>("import",
                "./Components/Pages/AlertUser.razor.js");

            await module.InvokeVoidAsync("addHandlers");
        }
    }

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

Az előző példában JSDisconnectedException megtorpan a modul-eltávolítás során, ha BlazorSignalR áramköre elveszik. Ha az előző kódot egy Blazor WebAssembly alkalmazásban használják, nincs SignalR megszakadó kapcsolat, így eltávolíthatja a try-catch blokkot, és elhagyhatja a modult (await module.DisposeAsync();) megsemmisítő sort. További információ: ASP.NET Core Blazor JavaScript-együttműködés (JS interop).

További információ:

Aszinkron JavaScript-hívások

A JS interop hívások aszinkronok, függetlenül attól, hogy a hívott kód szinkron vagy aszinkron. A hívások aszinkron módon biztosítják, hogy az összetevők kompatibilisek legyenek a kiszolgálóoldali és az ügyféloldali renderelési modellek között. A kiszolgálóoldali renderelés bevezetésekor JS interop hívásoknak aszinkronnak kell lenniük, mert hálózati kapcsolaton keresztül küldik őket. A kizárólag ügyféloldali renderelést alkalmazó alkalmazások esetében a szinkron JS interop hívások támogatottak.

További információkért lásd a következő cikkeket:

További információ: JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor.

Objektum szerializálása

Blazor System.Text.Json használ szerializáláshoz az alábbi követelményekkel és alapértelmezett viselkedéssel:

  • A típusoknak alapértelmezett konstruktorral kell rendelkezniük, a get/set hozzáférőknek nyilvánosnak kell lenniük, a mezőket pedig soha nem szerializálják.
  • A globális alapértelmezett szerializálás nem testreszabható a meglévő összetevőtárak feltörésének, a teljesítményre és a biztonságra gyakorolt hatás, valamint a megbízhatóság csökkentésének elkerülése érdekében.
  • A .NET-tagok nevének szerializálása kisbetűs JSON-kulcsneveket eredményez.
  • A JSON deszerializálva van JsonElement C#-példányként, ami lehetővé teszi a vegyes burkolatot. A C#-modell tulajdonságaihoz való hozzárendelés belső típuskonverziója a várt módon működik, annak ellenére, hogy a JSON-kulcsnevek és a C# tulajdonságnevek között vannak esetérzékenységi különbségek.
  • Az összetett keretrendszertípusokat az IL Trimmer eltávolíthatja a közzétételkor , és nem jelenik meg az interop- vagy JSON-szerializáláshoz/deszerializáláshoz JS . Javasoljuk, hogy az IL Trimmer által levágott típusokhoz hozzon létre egyéni típusokat.
  • Blazor mindig a reflektálására támaszkodik a JSON-szerializáláshoz, beleértve a C# forrásgeneráláshasználatát is. Ha a JsonSerializerIsReflectionEnabledByDefault értékét false-re állítja az alkalmazás projektfájljában, akkor a szerializálási kísérlet során hiba történik.

JsonConverter API egyéni szerializáláshoz érhető el. A tulajdonságok egy [JsonConverter] attribútummal jegyzetelhetők, amely felülbírálja egy meglévő adattípus alapértelmezett szerializálását.

További információkért tekintse meg a .NET dokumentációjának következő erőforrásait:

Blazor támogatja az optimalizált bájttömböket JS interop, amelyek elkerülik a bájttömbök Base64-be való kódolását/dekódolását. Az alkalmazás egyéni szerializálást alkalmazhat, és átadhatja az eredményként kapott bájtokat. További információ: JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor.

Blazor támogatja a nem sorosított JS interopot, amikor nagy mennyiségű .NET-objektumot gyorsan szerializálnak, vagy amikor nagy .NET-objektumokat vagy sok .NET-objektumot kell szerializálni. További információ: JavaScript-függvények meghívása a .NET-metódusokból ASP.NET Core Blazor.

DOM-tisztítási feladatok az összetevők ártalmatlanítása során

Ne hajtsa végre a JS feladatközi kódot DOM-takarítási feladatokra az összetevők eltávolítása során. Ehelyett használja a MutationObserver mintát a JavaScriptben (JS) az ügyfélen a következő okokból:

  • Lehetséges, hogy az összetevőt eltávolították a DOM-ból, mire a törlési kód végrehajtása megtörténik Dispose{Async}.
  • A kiszolgálóoldali renderelés során előfordulhat, hogy mire a törlési kódja végrehajtásra kerül a Blazor-ben, a keretrendszer már eltávolította a Dispose{Async} renderelőt.

A MutationObserver minta lehetővé teszi egy függvény futtatását, amikor egy elemet eltávolít a DOM-ból.

Az alábbi példában a DOMCleanup összetevő:

  • Tartalmaz egy <div> egy id-vel cleanupDiv. A <div> elemet a rendszer eltávolítja a DOM-ból, valamint az összetevő többi DOM-jelölőjét is, amikor az összetevőt eltávolítják a DOM-ból.
  • Betölti a DOMCleanupJS osztályt a DOMCleanup.razor.js fájlból, és meghívja a createObserver függvényt a MutationObserver visszahívás beállításához. Ezeket a feladatokat az OnAfterRenderAsync életciklus-módszervégzi el.

DOMCleanup.razor:

@page "/dom-cleanup"
@implements IAsyncDisposable
@inject IJSRuntime JS

<h1>DOM Cleanup Example</h1>

<div id="cleanupDiv"></div>

@code {
    private IJSObjectReference? module;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            module = await JS.InvokeAsync<IJSObjectReference>(
                "import", "./Components/Pages/DOMCleanup.razor.js");

            await module.InvokeVoidAsync("DOMCleanup.createObserver");
        }
    }

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

Az előző példában JSDisconnectedException megtorpan a modul-eltávolítás során, ha BlazorSignalR áramköre elveszik. Ha az előző kódot egy Blazor WebAssembly alkalmazásban használják, nincs SignalR megszakadó kapcsolat, így eltávolíthatja a try-catch blokkot, és elhagyhatja a modult (await module.DisposeAsync();) megsemmisítő sort. További információ: ASP.NET Core Blazor JavaScript-együttműködés (JS interop).

Az alábbi példában a MutationObserver visszahívás végrehajtása minden alkalommal megtörténik, amikor DOM-módosítás történik. Hajtsa végre a törlési kódot, amikor a if utasítás megerősíti, hogy a célelem (cleanupDiv) el lett távolítva (if (targetRemoved) { ... }). Fontos, hogy leválasztsa és törölje a MutationObserver, hogy elkerülje a memóriavesztést a törlési kód végrehajtása után.

DOMCleanup.razor.js az előző DOMCleanup összetevővel egymás mellett helyezve:

export class DOMCleanup {
  static observer;

  static createObserver() {
    const target = document.querySelector('#cleanupDiv');

    this.observer = new MutationObserver(function (mutations) {
      const targetRemoved = mutations.some(function (mutation) {
        const nodes = Array.from(mutation.removedNodes);
        return nodes.indexOf(target) !== -1;
      });

      if (targetRemoved) {
        // Cleanup resources here
        // ...

        // Disconnect and delete MutationObserver
        this.observer && this.observer.disconnect();
        delete this.observer;
      }
    });

    this.observer.observe(target.parentNode, { childList: true });
  }
}

window.DOMCleanup = DOMCleanup;

Az előző megközelítések a MutationObserver-t target.parentNode-hez csatolják, amely addig működik, amíg parentNode-t el nem távolítják a DOM-ból. Ez egy gyakori forgatókönyv, például egy új lapra való navigáláskor, amely miatt a teljes lapösszetevő el lesz távolítva a DOM-ból. Ilyen esetekben az oldalon belüli változásokat észlelő gyermekkomponensek nincsenek szakszerűen eltávolítva.

Ne feltételezzük, hogy a document.bodymegfigyelése target.parentNodehelyett jobb cél. A document.body megfigyelése teljesítménybeli következményekkel jár, mert a visszahívási logika a DOM-frissítések esetében is lefut, függetlenül attól, hogy van-e közük a saját elemedhez. Használja az alábbi módszerek egyikét:

  • Azokban az esetekben, amikor azonosítani tudja a megfigyelni kívánt elődcsomópontot, használja a MutationObserver. Ideális esetben ennek az ősnek a hatásköre azokra a módosításokra terjed ki, amelyeket meg akar figyelni, nem pedig a document.body-ra.
  • A MutationObserverhasználata helyett érdemes lehet egyéni elemet és disconnectedCallbackhasználni. Az esemény mindig aktiválódik, ha az egyéni elem leválasztva van, függetlenül attól, hogy hol található a DOM-ban a DOM-változáshoz képest.

JavaScript interop hívások áramkör nélkül

Ez a szakasz csak a kiszolgálóoldali alkalmazásokra vonatkozik.

A JavaScript (JS) interop-hívások nem adhatók ki BlazorSignalR áramkör leválasztása után. Áramkör nélkül az összetevők ártalmatlanítása során vagy bármely más időpontban, amikor áramkör nem létezik, az alábbi metódus hívások sikertelenek lesznek, és naplózza az üzenetet, hogy az áramkör szét van kapcsolva JSDisconnectedException:

A JSDisconnectedException naplózásának vagy az egyéni adatok naplózásának elkerülése érdekében a kivételt egy try-catch utasításban észlelheti.

Az alábbi összetevő-ártalmatlanítási példa esetében:

  • A kiszolgálóoldali összetevő implementálja a IAsyncDisposable.
  • module egy IJSObjectReference a(z) JS modul számára.
  • JSDisconnectedException el van fogva, és nincs naplózva.
  • Igény szerint az egyéni adatokat az catch utasításban tetszőleges naplószinten naplózhatja. Az alábbi példa nem naplóz egyéni információkat, mert feltételezi, hogy a fejlesztő nem törődik azzal, hogy mikor vagy hol vannak az áramkörök lekapcsolva a komponensek ártalmatlanítása során.
async ValueTask IAsyncDisposable.DisposeAsync()
{
    try
    {
        if (module is not null)
        {
            await module.DisposeAsync();
        }
    }
    catch (JSDisconnectedException)
    {
    }
}

Ha törölnie kell a saját JS objektumait, vagy más JS kódot kell végrehajtania az ügyfélen, miután egy áramkör megszakadt egy kiszolgálóoldali Blazor alkalmazásban, használja a MutationObserverJS mintát az ügyfélen. A MutationObserver minta lehetővé teszi egy függvény futtatását, amikor egy elemet eltávolít a DOM-ból.

További információkért lásd a következő cikkeket:

Gyorsítótárazott JavaScript-fájlok

A JavaScript (JS) fájlok és egyéb statikus objektumok általában nem gyorsítótárazódnak az ügyféloldalon a Development környezetben történő fejlesztés során. A fejlesztés alatt a statikus eszközkérelmek között szerepel a Cache-Control fejléc, amelynek értéke no-cache, illetve max-age nulla (0).

A Production környezetbena JS fájlokat általában az ügyfelek gyorsítótárazzák.

Az ügyféloldali gyorsítótárazás böngészőkben való letiltásához a fejlesztők általában az alábbi módszerek egyikét alkalmazzák:

  • Tiltsa le a gyorsítótárazást, ha a böngésző fejlesztői eszközeinek konzolja meg van nyitva. Útmutatást az egyes böngészőfenntartók fejlesztői eszközeinek dokumentációjában talál:
  • A Blazor alkalmazás bármely weblapjának manuális böngészőfrissítése JS fájlok kiszolgálóról való újbóli betöltéséhez. ASP.NET Core HTTP-gyorsítótárazási middleware-je mindig tiszteletben tartja az ügyfél által küldött érvényes no-cache Cache-Control fejlécet.

További információ:

A JavaScript interop-hívások méretkorlátjai

Ez a szakasz csak a kiszolgálóoldali alkalmazások interaktív összetevőire vonatkozik. Az ügyféloldali összetevők esetében a keretrendszer nem korlátozza a JavaScript (JS) interop bemenetek és kimenetek méretét.

A kiszolgálói alkalmazások interaktív összetevői esetén az ügyféltől a kiszolgálóhoz történő adatok átadására szolgáló JS interop hívásokat a központi metódusok számára engedélyezett maximális bejövő SignalR üzenetméret korlátozza, és ezt a HubOptions.MaximumReceiveMessageSize határozza meg (alapértelmezés: 32 KB). A JS-nél nagyobb SignalR .NET-MaximumReceiveMessageSize üzenetek hibát okoznak. A keretrendszer nem korlátozza az SignalR-üzenetek méretét a központtól az ügyfélig. A méretkorlátról, a hibaüzenetekkel és az üzenetméretkorlátok kezelésével kapcsolatos további információkért tekintse meg ASP.NET Core BlazorSignalR útmutatóját.

Annak meghatározása, hogy az alkalmazás hol fut

Ha fontos, hogy az alkalmazás tudja, hol fut a kód JS interop hívásokhoz, a OperatingSystem.IsBrowser segítségével állapítsa meg, hogy az összetevő a WebAssembly böngészőkörnyezetében fut-e.