Bagikan melalui


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

Artikel ini menjelaskan cara memuat JavaScript (JS) di Aplikasi Web dengan penyajian sisi server statis (SSR statis) dan navigasi yang ditingkatkanBlazor.

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 JSafterWebStarteduntuk melakukan logika inisialisasi dan menggunakan pendengar peristiwa (blazor.addEventListener("enhancedload", callback)) untuk mendengarkan pembaruan halaman yang disebabkan oleh navigasi yang ditingkatkan.

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 Di Aplikasi Web, 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');
}

Razor Di Pustaka Kelas (RCL) (contoh RCL diberi nama BlazorPageScript), tambahkan modul berikut.

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

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).

Contoh implementasi tanpa menggunakan RCL

Pendekatan yang dijelaskan dalam artikel ini dapat diimplementasikan langsung di Blazor Aplikasi Web tanpa menggunakan Razor pustaka kelas (RCL). Misalnya, lihat Mengaktifkan pembuatan kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core Blazor Web App.