Topik temu duga representatif

Temu Duga Frontend: Bagaimana Anda Mereka Bentuk Kitaran Hayat Custom Element yang Mudah Diselenggara?

FrontendSukar
Pasukan Editorial Offer.ccDiterbitkan Dikemas kini

Soalan

Reka bentuk Custom Element yang boleh diguna semula oleh pelbagai pasukan dan rangka kerja. Bagaimanakah anda menggunakan constructor, connectedCallback, disconnectedCallback, dan attributeChangedCallback, serta mengendalikan Shadow DOM, penyelarasan atribut/sifat, pendaftaran pendua, dan sokongan pelayar?

Kehendak soalan dan skop

Anda mesti menyediakan elemen tersuai <account-summary> untuk hos yang dirender oleh React, Vue, atau templat pelayan. Ia memaparkan status akaun, bertindak balas terhadap atribut status, menghantar (dispatch) acara awam, dan melepaskan langganan apabila dialih keluar daripada dokumen. Gaya mesti kekal terkandung tanpa kehilangan semantik papan kekunci atau teknologi bantuan.

Andaikan elemen tersuai autonomi (autonomous custom element) terlebih dahulu. Jika syaratnya adalah untuk melanjutkan button asli atau elemen terbina dalam yang lain, nilaikan elemen terbina dalam tersuai (customized built-in elements) secara berasingan kerana sokongan pelayar mengubah reka bentuknya. Temu duga ini menguji sempadan kitaran hayat dan pemilikan sumber, bukannya sintaks komponen rangka kerja.

Perkara yang dinilai oleh penemu duga

  • Sama ada anda boleh memberikan tanggungjawab yang berbeza kepada constructor, connectedCallback, disconnectedCallback, dan pemerhatian atribut.
  • Sama ada anda mengendalikan penyambungan semula (reconnects), pemindahan (moves), peningkatan taraf (upgrades), dan atribut awal dan bukannya menganggap setiap panggilan balik hanya berjalan sekali.
  • Sama ada anda menghubungkan enkapsulasi Shadow DOM dengan kebolehcapaian, penyebaran acara, dan integrasi hos.
  • Sama ada anda boleh mencadangkan pendaftaran idempoten, keserasian, pembersihan, dan ujian.

Menghafal nama-nama panggilan balik sahaja tidak mencukupi. Jawapan yang mantap mentakrifkan pemilikan sumber terlebih dahulu, kemudian menerangkan bagaimana sambungan, atribut, dan keadaan render berinteraksi.

Soalan untuk dijelaskan terlebih dahulu

  1. Adakah elemen tersebut mesti melanjutkan elemen semantik asli? Jika ya, sintaks is dan sokongan pelayar akan mempengaruhi pilihan tersebut.
  2. Adakah input berupa rentetan, atau pemanggil mesti menghantar objek dan panggilan balik? Nilai kompleks memerlukan kontrak sifat atau kaedah yang jelas.
  3. Adakah keadaan (state) mesti kekal apabila dipindahkan dalam dokumen yang sama? Ini menentukan sama ada perlu menilai connectedMoveCallback atau mengekalkan keadaan secara eksplisit.
  4. Adakah acara mesti merentasi sempadan Shadow DOM? Buat persetujuan tentang bubbles, composed, dan muatan (payload) sebelum memilih API acara.

Rangka kerja jawapan 30 saat

“Saya mengasingkan takrifan, sambungan, penyelarasan atribut, rendering, dan pembersihan. constructor hanya memulakan medan ringan dan tidak bergantung pada nod anak atau dokumen luaran. connectedCallback mewujudkan langganan dan merender secara idempoten; disconnectedCallback melepaskan pendengar, pemasa, dan pemerhati. Saya hanya memerhatikan atribut yang diperlukan, menormalkan nilai rentetannya dalam attributeChangedCallback, dan menghalakan kemas kini melalui satu laluan render. Shadow DOM mengandungi gaya pelaksanaan, manakala semantik awam, fokus, dan acara kekal sebagai sebahagian daripada kontrak hos yang diuji. Saya mengakhiri dengan ujian untuk penyambungan semula, pemindahan, atribut awal, penyingkiran, peningkatan taraf, dan pelayar yang tidak disokong.”

Analisis langkah demi langkah

1. Takrifkan pemilikan keadaan dan sumber

Jejaki keadaan disambungkan, dilanggan, dan dirender secara berasingan. constructor tidak boleh membaca DOM luar atau memulakan kerja rangkaian: pelayar boleh membina elemen sebelum menyambungkannya ke dokumen.

js
class AccountSummary extends HTMLElement {
  static observedAttributes = ["status"];
  #connected = false;
  #unsubscribe = null;
  #root;

  constructor() {
    super();
    this.#root = this.attachShadow({ mode: "open" });
  }
}

2. Jadikan connectedCallback selamat untuk diulang

Sesuatu elemen boleh dialih keluar dan dimasukkan semula, jadi connectedCallback tidak boleh mendaftarkan pendengar lain tanpa syarat. Semak keadaan sambungan, wujudkan langganan, dan jadikan rendering selamat untuk dipanggil berulang kali.

js
connectedCallback() {
  if (this.#connected) return;
  this.#connected = true;
  this.#unsubscribe = accountStore.subscribe(() => this.#render());
  this.#render();
}

3. Lepaskan setiap kesan sampingan dalam disconnectedCallback

Pendengar acara, setInterval, ResizeObserver, AbortController, dan langganan stor memerlukan pemilik yang jelas. Kosongkan rujukan selepas pembersihan supaya sambungan kemudian mencipta tepat satu set sumber baharu.

js
disconnectedCallback() {
  this.#unsubscribe?.();
  this.#unsubscribe = null;
  this.#connected = false;
}

Corak pemindahan yang lebih lama boleh mencetuskan panggilan balik putus dan sambung secara berturutan. Jika mengekalkan keadaan merentasi pemindahan adalah penting, nilaikan connectedMoveCallback di mana disokong, atau bina semula daripada atribut dan keadaan tahan lama dan bukannya bergantung pada urutan panggilan balik.

4. Perhatikan atribut dan asingkan sifat

observedAttributes hanya perlu menyenaraikan nilai yang memerlukan penyelarasan. attributeChangedCallback boleh berjalan untuk atribut awal semasa penghuraian (parsing), jadi “berubah” tidak semestinya bermakna pengguna baru sahaja mengeditnya. Kendalikan nilai awal dan nilai terkemudian melalui laluan yang sama dan elakkan daripada menulis semula atribut yang sama daripada panggilan baliknya.

js
attributeChangedCallback(name, oldValue, newValue) {
  if (oldValue === newValue) return;
  if (name === "status") this.#renderStatus(newValue ?? "unknown");
}

Atribut rentetan berfungsi dengan baik untuk HTML deklaratif. Hantar tatasusunan, objek, dan panggilan balik melalui sifat atau kaedah yang didokumentasikan dan bukannya memperlakukan rentetan JSON sewenang-wenangnya sebagai protokol tanpa had.

5. Reka bentuk Shadow DOM dan kontrak hos

Shadow DOM mengasingkan CSS dalaman dan pertanyaan DOM, tetapi ia tidak membekalkan semantik secara automatik. Gunakan peranan (roles) yang betul, nama yang boleh diakses, urutan fokus, dan keterlihatan. Jika hos mesti mengambil bahagian dalam susun atur, dedahkan kontrak yang terhad melalui :host, slot, atau sifat tersuai CSS.

css
:host { display: block; }
:host([hidden]) { display: none; }

Bagi acara yang mesti diperhatikan oleh hos, tetapkan bubbles dan composed secara sengaja dan pastikan muatan kekal stabil. Merentasi sempadan tidak memerlukan mendedahkan nod dalaman.

6. Kendalikan pendaftaran, peningkatan taraf, dan keserasian

Sesuatu nama hanya boleh ditakrifkan sekali dalam pendaftaran global. Pustaka yang dikongsi harus menggunakan awalan ruang nama dan menyemak customElements.get(name) sebelum mentakrifkan; jangan sembunyikan pertembungan dengan menangkap pengecualian (exception). Elemen yang dihuraikan sebelum pendaftaran akan ditingkatkan tarafnya selepas takrifan, jadi pelaksanaan mesti menyokong susunan tersebut.

js
const name = "account-summary";
if (!customElements.get(name)) {
  customElements.define(name, AccountSummary);
}

Elemen autonomi biasanya lebih mudah untuk digunakan merentasi pelayar. MDN mendokumentasikan batasan Safari untuk customized built-in elements; jika melanjutkan elemen asli adalah wajib, sahkan matriks pelayar sasaran dan sediakan sandaran (fallback).

Contoh jawapan berkualiti tinggi

Saya akan menulis jadual pemilikan terlebih dahulu: constructor mencipta Shadow Root dan medan lalai, connectedCallback melanggan dan merender, disconnectedCallback membatalkan langganan, dan attributeChangedCallback hanya mengendalikan konfigurasi deklaratif yang diperhatikan. Setiap fasa boleh diulang atau dilangkau dengan selamat; “berjalan sekali” tidak dianggap sebagai jaminan kitaran hayat.

Saya akan memilih autonomous custom element dan melindungi pendaftaran dengan customElements.get. Shadow DOM mengandungi gaya pelaksanaan, manakala komponen masih mendedahkan nama yang boleh diakses, tingkah laku fokus, dan kontrak acara. Acara merentasi sempadan menggunakan tetapan bubbles dan composed yang eksplisit dengan muatan yang terhad. Atribut membawa konfigurasi deklaratif primitif; objek kompleks menggunakan sifat atau kaedah.

Pengesahan merangkumi peningkatan taraf huraian-sebelum-takrif (parse-before-define), atribut awal, penyambungan semula, pemindahan, pembersihan, acara rentas sempadan, tingkah laku papan kekunci, dan semantik pembaca skrin. Jika customized built-in elements diperlukan, saya akan mengesahkan matriks pelayar terlebih dahulu, kemudian memilih laluan tersebut hanya jika kos keserasian boleh diterima.

Kesilapan lazim dan penambahbaikan

  • Kesilapan → Membaca nod anak atau memulakan permintaan dalam constructor → Sebab ia gagal → Elemen mungkin belum disambungkan lagi → Penambahbaikan → Alihkan kerja dokumen dan rangkaian ke connectedCallback dan ikat permintaan pada AbortController.
  • Kesilapan → Menambah pendengar pada setiap connectedCallback → Sebab ia gagal → Penyambungan semula menduplikasi kerja dan membocorkan memori → Penambahbaikan → Simpan pemegang langganan dan jadikan persediaan/pembersihan sebagai pasangan idempoten.
  • Kesilapan → Memanggil setAttribute tanpa syarat daripada panggilan balik atribut → Sebab ia gagal → Ia boleh membentuk gelung panggilan balik, dan penghuraian atribut awal juga memanggil panggilan balik tersebut → Penambahbaikan → Bandingkan nilai lama dan baharu, normalkan sekali, dan elakkan daripada menulis atribut yang sama.
  • Kesilapan → Menganggap Shadow DOM sebagai penyelesaian kebolehcapaian → Sebab ia gagal → Enkapsulasi tidak mencipta nama, fokus, atau semantik → Penambahbaikan → Uji kontrak awam dengan aliran papan kekunci dan teknologi bantuan.

Soalan susulan dan respons

Elemen dihuraikan sebelum ia ditakrifkan. Bagaimanakah anda mengelakkan kelipan (flash)?

Anggap elemen yang belum ditakrifkan sebagai keadaan yang boleh ditingkatkan tarafnya dan sediakan kandungan sandaran yang boleh dibaca atau keadaan memuatkan. Pelayar meningkatkan taraf tika (instances) selepas pendaftaran. Jika kod mesti menunggu, hos boleh await customElements.whenDefined("account-summary"), tetapi keseluruhan halaman tidak sepatutnya disekat oleh skrip komponen.

Patutkah objek kompleks diletakkan dalam atribut?

Biasanya tidak. Atribut adalah rentetan dan sesuai dengan konfigurasi deklaratif yang boleh disiri; objek dan panggilan balik harus menggunakan sifat atau kaedah yang didokumentasikan dengan tingkah laku pra- dan pasca-sambungan yang jelas. Jika pensirian diperlukan, nyatakan versi, saiz, dan pengendalian ralat huraian.

Mengapakah hos tidak menerima klik daripada butang di dalam Shadow DOM?

Penyebaran merentasi sempadan bergantung pada composed; penggelembungan ke atas (upward bubbling) bergantung pada bubbles. Hantar acara semantik yang stabil dengan kedua-dua pilihan dipilih secara eksplisit. Di luar sempadan, sasaran mungkin disasarkan semula (retargeted) kepada shadow host, jadi hos tidak seharusnya bergantung pada nod dalaman.

Bagaimanakah anda membuktikan penyambungan semula tidak bocor?

Masukkan dan alih keluar tika yang sama berulang kali, kira langganan, penghantaran acara, dan pemegang pemasa, kemudian gunakan snapshot memori untuk mengesahkan bahawa nod lama boleh dikumpul oleh pengumpul sampah. Rangkumi panggilan balik atribut awal, pemindahan, dan peningkatan taraf huraian-sebelum-takrif; render pertama sahaja membuktikan sangat sedikit perkara.

Sumber awam

Soalan berkaitan