Bagikan melalui


ASP.NET Core Blazor JavaScript dengan penyajian sisi server statis (SSR statis)

Catatan

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Penting

Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.

Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Artikel ini menjelaskan cara memuat JavaScript (JS) dalam dengan penyajian sisi server statis (SSR statis) dan Blazor Web App yang ditingkatkan.

Beberapa aplikasi bergantung pada JS untuk melakukan tugas inisialisasi yang khusus untuk setiap halaman. Saat menggunakan Blazorfitur navigasi yang ditingkatkan, yang memungkinkan pengguna untuk menghindari memuat ulang seluruh halaman, spesifik halaman JS mungkin tidak dijalankan lagi seperti yang diharapkan setiap kali navigasi halaman yang ditingkatkan terjadi.

Untuk menghindari masalah ini, kami tidak merekomendasikan untuk mengandalkan elemen khusus <script> halaman yang ditempatkan di luar file tata letak yang diterapkan ke komponen. Sebagai gantinya, skrip harus mendaftarkan penginisialisasi afterWebStartedJS untuk melakukan logika inisialisasi dan menggunakan pendengar peristiwa untuk mendengarkan pembaruan halaman yang disebabkan oleh navigasi yang ditingkatkan.

Peristiwa

Dalam contoh "event listener" berikut, penampung {CALLBACK} adalah fungsi "callback".

  • Mulai navigasi yang disempurnakan (enhancednavigationstart) memicu panggilan balik sebelum navigasi yang ditingkatkan terjadi:

    blazor.addEventListener("enhancednavigationstart", {CALLBACK});
    
  • Akhir navigasi yang ditingkatkan (enhancednavigationend) memicu panggilan balik setelah navigasi yang ditingkatkan terjadi:

    blazor.addEventListener("enhancednavigationend", {CALLBACK});
    
  • Peningkatan beban halaman navigasi (enhancedload) memicu panggilan balik setiap kali halaman diperbarui karena navigasi yang ditingkatkan, termasuk pembaruan streaming :

    blazor.addEventListener("enhancedload", {CALLBACK});
    

Untuk menghindari masalah ini, kami tidak merekomendasikan untuk mengandalkan elemen khusus <script> halaman yang ditempatkan di luar file tata letak yang diterapkan ke komponen. Sebagai gantinya, skrip harus mendaftarkan penginisialisasi afterWebStartedJS untuk melakukan logika inisialisasi dan menggunakan pendengar acara untuk mendengarkan pembaruan halaman yang disebabkan oleh navigasi yang ditingkatkan.

blazor.addEventListener("enhancedload", {CALLBACK});

Dalam contoh sebelumnya, tempat penampung {CALLBACK} adalah fungsi panggilan balik.

Contoh skrip pemuatan halaman yang disempurnakan

Contoh berikut menunjukkan salah satu cara untuk mengonfigurasi JS kode untuk dijalankan saat halaman yang dirender secara statis dengan navigasi yang ditingkatkan awalnya dimuat atau diperbarui.

Contoh komponen berikut PageWithScript adalah komponen dalam aplikasi yang mengharuskan skrip dijalankan dengan SSR statis dan navigasi yang disempurnakan. Contoh komponen berikut menyertakan PageScript komponen dari Razor pustaka kelas (RCL) yang ditambahkan ke solusi nanti dalam artikel ini.

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.

Blazor Web AppDi , tambahkan file yang dikolokasi JS berikut:

  • onLoad dipanggil ketika skrip ditambahkan ke halaman.
  • onUpdate dipanggil ketika skrip masih ada di halaman setelah pembaruan yang ditingkatkan.
  • onDispose dipanggil ketika skrip dihapus dari halaman setelah pembaruan yang ditingkatkan.

Components/Pages/PageWithScript.razor.js:

export function onLoad() {
  console.log('Loaded');
}

export function onUpdate() {
  console.log('Updated');
}

export function onDispose() {
  console.log('Disposed');
}

Dalam Pustaka Kelas (RCL) (contoh RCL diberi nama ), tambahkan modul berikut, yang merupakan penginisialisasi .

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);
}

Apakah tidak menambahkan tag <script> ke komponen akar aplikasi, biasanya kompponen App, untuk BlazorPageScript.lib.module.js karena modul dalam hal ini adalah inisialisasi JS (afterWebStarted). JS inisialisasi terdeteksi dan dimuat secara otomatis oleh kerangka kerja Blazor.

Di RCL, tambahkan komponen berikut PageScript .

PageScript.razor:

<page-script src="@Src"></page-script>

@code {
    [Parameter]
    [EditorRequired]
    public string Src { get; set; } = default!;
}

Komponen PageScript biasanya berfungsi pada tingkat atas halaman.

Jika Anda menempatkan PageScript komponen dalam tata letak aplikasi (misalnya, MainLayout.razor), yang menghasilkan dibagikan PageScript di antara halaman yang menggunakan tata letak, maka komponen hanya berjalan onLoad setelah pemuatan ulang halaman penuh dan onUpdate ketika pembaruan halaman yang ditingkatkan terjadi, termasuk navigasi yang ditingkatkan.

Untuk menggunakan kembali modul yang sama di antara halaman, tetapi meminta onLoad panggilan balik dan onDispose pada setiap perubahan halaman, tambahkan string kueri ke akhir skrip sehingga dikenali sebagai modul yang berbeda. Aplikasi dapat mengadopsi konvensi penggunaan nama komponen sebagai nilai string kueri. Dalam contoh berikut, string kueri adalah "counter" karena referensi komponen ini PageScript ditempatkan dalam komponen Counter . Ini hanyalah saran, dan Anda dapat menggunakan skema string kueri apa pun yang Anda sukai.

<PageScript Src="./Components/Pages/PageWithScript.razor.js?counter" />

Untuk memantau perubahan dalam elemen DOM tertentu, gunakan MutationObserver pola di JS pada klien. Untuk informasi selengkapnya, lihat ASP.NET Blazor interoperabilitas Core JavaScript (JS interop).

Implementasi tanpa menggunakan RCL

Pendekatan yang dijelaskan dalam artikel ini dapat diimplementasikan langsung dalam Blazor Web App tanpa menggunakan pustaka kelas Razor (RCL) dengan memindahkan aset RCL ke dalam aplikasi. Namun, penggunaan RCL nyaman karena RCL dapat dikemas ke dalam paket NuGet untuk dikonsumsi oleh aplikasi Blazor di seluruh organisasi.

Jika Anda memindahkan aset ke Blazor Web App, pastikan untuk mengganti nama modul (BlazorPageScript.lib.module.js) agar sesuai dengan aplikasi sesuai aturan penamaan file untuk penginisialisasi JS. Jika file tidak diberi nama dengan benar, Blazor tidak dapat mendeteksi dan memuat modul, dan peristiwa afterWebStarted tidak dijalankan secara otomatis saat aplikasi dimulai.