Topik wawancara representatif

Wawancara Frontend: Bagaimana sidebar kustom merespons permintaan tutup bawaan perangkat?

FrontendSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Rancang sidebar seluler yang dapat digeser yang menutup dengan Escape di desktop dan gestur kembali di Android, sambil melindungi formulir yang belum disimpan. Jelaskan CloseWatcher, fallback, dan perilaku fokus.

Perintah dan konteks

Rancang sidebar seluler yang dapat digeser. Pengguna desktop mengharapkan Escape untuk menutupnya, pengguna Android mengharapkan gestur atau tombol kembali, dan formulir yang belum disimpan harus memerlukan konfirmasi. Gunakan CloseWatcher untuk satu alur penutupan dan jelaskan cancel, close, requestClose(), destroy(), fokus, beberapa watcher, browser yang tidak didukung, dan batasan riwayat.

MDN menjelaskan CloseWatcher sebagai antarmuka untuk membuat komponen kustom merespons tindakan penutupan khusus perangkat. HTML Standard juga mendefinisikan pengelompokan close-watcher dan perlindungan seputar penyalahgunaan tindakan riwayat. Artikel ini merangkum materi publik dan tidak mengklaim sebagai pertanyaan wawancara khusus perusahaan mana pun.

Apa yang sedang diuji oleh pewawancara

Pewawancara ingin melihat apakah Anda membedakan permintaan penutupan dari penutupan langsung, mencegah penutupan selama fase cancel, dan menjaga satu penangan close bertanggung jawab atas pembersihan UI. Jawaban yang kuat menyebutkan aktivasi pengguna, pengelompokan beberapa watcher, masa pakai AbortSignal, pengembalian fokus, dan fallback tombol eksplisit; jawaban yang lemah hanya mendengarkan keydown.

Pertanyaan untuk diklarifikasi terlebih dahulu

  • Apakah sidebar bersifat modal, non-modal, atau terikat pada status navigasi riwayat?
  • Haruskah konten yang belum disimpan memblokir setiap permintaan penutupan atau hanya ketika bidang tertentu kotor (dirty)?
  • Haruskah gestur kembali menutup komponen atau menavigasi ke entri riwayat sebelumnya?
  • Apakah browser target mendukung CloseWatcher, dan bolehkah fitur tersebut diturunkan ke tombol tutup eksplisit?

Jawaban 30 detik

“Saya akan menormalkan setiap titik masuk penutupan sebagai permintaan penutupan. Saat sidebar terbuka, buat CloseWatcher dengan AbortSignal. Di cancel, periksa apakah formulir kotor; cegah permintaan dan tampilkan konfirmasi jika kotor, jika tidak, izinkan. close menyembunyikan komponen, memulihkan fokus, dan membersihkan sumber daya, dan tombol tutup eksplisit mengikuti jalur yang sama. Browser yang tidak didukung mempertahankan tombol dan fallback Escape terbatas; browser atau router memiliki navigasi kembali ketika tidak ada komponen yang dapat ditutup.”

Solusi langkah demi langkah

Pisahkan kedua tindakan tersebut. requestClose() mensimulasikan permintaan penutupan perangkat dan memicu cancel; jika tidak dicegah, close mengikuti. close() langsung memicu close tanpa cancel, sedangkan destroy() hanya menonaktifkan watcher. Setelah menyimpan, melepas (unmounting), atau meninggalkan rute, pilih secara eksplisit permintaan penutupan atau pembersihan paksa daripada mencampuradukkan artinya.

js
function openDrawer() {
  const controller = new AbortController();
  const watcher = new CloseWatcher({ signal: controller.signal });

  watcher.addEventListener("cancel", (event) => {
    if (!formIsDirty()) return;
    event.preventDefault();
    showDiscardConfirmation(() => watcher.close());
  });

  watcher.addEventListener("close", () => {
    hideDrawer();
    restoreFocusToTrigger();
    controller.abort();
  });

  return { watcher, controller };
}

Dialog konfirmasi tidak boleh membuat watcher yang tidak dapat ditutup secara rekursif. Setelah konfirmasi pembuangan eksplisit, panggil close() milik watcher saat ini; membatalkan konfirmasi membuat sidebar tetap terbuka. Setelah menyimpan, bersihkan status kotor dan panggil requestClose() sehingga jalur pembersihan yang sama berjalan.

Perilaku fokus tergantung pada komponen. Sidebar modal harus memindahkan fokus ke tajuk yang mudah dipahami atau kontrol pertama dan mengembalikannya ke pemicu saat ditutup. Panel non-modal tidak boleh mencuri fokus, tetapi masih memerlukan tombol tutup yang dapat dijangkau dan status yang terlihat. Permintaan penutupan harus memperbarui nama yang dapat diakses, scrim, penguncian gulir, dan urutan keyboard, bukan hanya mengalihkan CSS.

Beberapa watcher memiliki batasan khusus. Tanpa aktivasi pengguna, spesifikasi memungkinkan watcher untuk dikelompokkan, sehingga satu permintaan penutupan dapat menutup beberapa di antaranya. Jangan membuat watcher tanpa syarat untuk setiap panel kecil. Lebih baik gunakan satu komponen tingkat atas yang dapat ditutup untuk memiliki watcher; anak-anak meminta penutupan melalui event, dan proses unmount memanggil destroy() atau membatalkan sinyal terkait.

Gestur kembali bukan sekadar klik. Platform dapat memperlakukannya sebagai traversal riwayat atau permintaan penutupan, dan pengelola close-watcher browser memilih targetnya. Aplikasi harus mengonfirmasi hanya ketika dapat mencegat dan komponen sedang terbuka; tanpa komponen yang dapat ditutup, pengembalian riwayat normal harus dilanjutkan. Jangan memblokir popstate atau gestur kembali secara global untuk melindungi satu formulir lokal.

Deteksi kemampuan melindungi jalur inti. Periksa window.CloseWatcher sebelum membuatnya. Jika tidak didukung, pertahankan tombol tutup eksplisit, tambahkan pendengar Escape terbatas jika diperlukan, dan biarkan router yang ada mengelola perilaku kembali. Jangan mengklaim bahwa pendengar kustom mereproduksi sepenuhnya semantik kembali Android. Ukur dukungan, permintaan yang diblokir, pembuangan setelah konfirmasi, dan kegagalan pemulihan fokus.

Contoh jawaban yang kuat

Saya akan menormalkan setiap entri penutupan sidebar sebagai permintaan penutupan. Saat dibuka, buat CloseWatcher dengan AbortSignal. cancel hanya memeriksa status yang belum disimpan: saat kotor, panggil preventDefault() dan tampilkan konfirmasi; saat bersih, izinkan permintaan. Setelah konfirmasi pembuangan, panggil close(); setelah menyimpan, bersihkan status kotor dan panggil requestClose(). close adalah satu-satunya titik pembersihan UI: sembunyikan panel, pulihkan fokus ke pemicu, hapus penguncian gulir, dan hentikan watcher.

Saya akan membatasi jumlah watcher sehingga instance yang tidak diaktifkan tidak dikelompokkan secara tidak sengaja; unmount atau perubahan rute menghancurkannya. Komponen modal dan non-modal mendapatkan aturan fokus dan scrim yang berbeda, dan gestur kembali mencapai riwayat browser saat tidak ada komponen yang terbuka. Browser tanpa CloseWatcher mempertahankan tombol eksplisit dan fallback keyboard terbatas tanpa memblokir navigasi inti. Metrik memvalidasi perilaku penutupan, konfirmasi, dan aksesibilitas.

Kesalahan umum

  • Gejala → Menggunakan close() untuk setiap titik masuk; mengapa gagal → Ini melewati fase konfirmasi belum disimpan; perbaikan → Niat pengguna dan platform menggunakan requestClose(), sedangkan pembersihan paksa menggunakan close().
  • Gejala → Hanya mendengarkan Escape; mengapa gagal → Kembali pada Android dan tindakan penutupan perangkat lainnya terlewatkan; perbaikan → Gunakan CloseWatcher dan pertahankan tombol eksplisit.
  • Gejala → Membuat watcher untuk setiap panel anak; mengapa gagal → Watcher yang tidak diaktifkan dapat dikelompokkan; perbaikan → Biarkan komponen penutup tingkat atas memiliki satu instance.
  • Gejala → Membiarkan fokus pada simpul tersembunyi; mengapa gagal → Pengguna keyboard dan teknologi asistif kehilangan posisi mereka; perbaikan → Simpan pemicu dan pulihkan fokus di close.
  • Gejala → Memblokir event kembali secara global; mengapa gagal → Navigasi riwayat rusak saat tidak ada komponen yang terbuka; perbaikan → Blokir hanya permintaan penutupan komponen yang terbuka saat konfirmasi diperlukan.

Pertanyaan lanjutan dan jawaban

Kapan Anda harus menggunakan requestClose() versus close()?

Gunakan requestClose() untuk niat pengguna atau platform karena memberikan cancel kesempatan untuk mencegah penutupan. Gunakan close() setelah konfirmasi pembuangan eksplisit, selama pembersihan unmount, atau kapan pun penutupan harus segera dilakukan. Keduanya harus menyatu pada penangan pembersihan close yang sama.

Haruskah dialog konfirmasi belum disimpan memiliki CloseWatcher sendiri?

Tidak harus. Berikan dialog konfirmasi tombol tutup eksplisit dan jalur fokus yang dapat diakses untuk menghindari rekursi atau penutupan berkelompok dengan watcher induk. Induk memanggil close() setelah konfirmasi; menutup anak hanya mengubah status konfirmasi.

Bagaimana Anda menangani beberapa panel yang terbuka?

Tentukan tumpukan atau kepemilikan tingkat atas: satu permintaan hanya menutup komponen teratas yang benar-benar dapat ditutup, sementara yang lain tetap terbuka. Jangan mengandalkan pengelompokan implisit dari watcher yang tidak diaktifkan sebagai tumpukan bisnis Anda; catat urutan dan kembalikan fokus dalam status aplikasi.

Apa fallback ketika CloseWatcher tidak didukung?

Pertahankan tombol tutup eksplisit dan penanganan Escape dasar, dengan menggunakan kembali konfirmasi status kotor, pemulihan fokus, dan fungsi pembersihan yang sama. Jangan mencegat gestur kembali atau riwayat secara global. Ukur kelompok yang mengalami penurunan versi sebelum memutuskan apakah akan memperluas peningkatan fitur.

Sumber publik

Pertanyaan terkait