Gesaan dan Konteks Berkaitan
Bina senarai tugas yang itemnya boleh disusun semula. Pengguna tetikus dan sentuhan boleh menyeret item, tetapi setiap susunan semula juga mesti boleh dilakukan dengan papan kekunci dan dengan klik atau ketik yang tidak memerlukan pergerakan menyeret. Pengguna pembaca skrin mesti dimaklumkan tentang item mana yang telah dialihkan dan kedudukan baharunya. Reka bentuk ini mesti mengekalkan fokus, menyokong pembatalan, mengelakkan kehilangan atau penduaan item, dan mengendalikan kegagalan penyimpanan tanpa menyebabkan susunan yang kelihatan menjadi kabur.
Andaikan senarai asas dirender sepenuhnya, setiap item mempunyai ID unik yang stabil, dan hanya satu item dialihkan pada satu masa. Menyusun semula dalam senarai maya (virtualized list), mengalihkan beberapa item yang dipilih, dan menyelesaikan pengeditan serentak adalah soalan susulan. Rangka kerja bukanlah keputusan utama: React boleh merender paparan, tetapi temu duga ini menguji pemodelan input, semantik yang boleh diakses, pemilikan keadaan (state ownership), dan pengesahan.
Menyeret ialah satu peningkatan (enhancement), bukan operasi perniagaan. Operasi perniagaan ialah “alihkan item X ke kedudukan akhir Y.” Penyeretan penuding, arahan papan kekunci, dan kawalan alih yang kelihatan semuanya harus memanggil operasi yang sama. Pengasingan ini menghalang tiga laluan input daripada menghasilkan tiga susunan yang berbeza secara halus.
Perkara yang Dinilai oleh Penemu Duga
Isyarat pertama ialah sama ada calon mengasingkan identiti daripada kedudukan. Indeks tatasusunan ialah kedudukan sementara, jadi ia tidak boleh dijadikan kekunci React atau identiti item yang kekal. ID item yang stabil memilih perkara yang dialihkan; indeks akhir atau ID stabil bersebelahan memilih tempat ia dialihkan.
Isyarat kedua ialah ketepatan kebolehcapaian. Operasi papan kekunci WCAG dan keperluan pergerakan menyeret WCAG 2.2 adalah berkaitan tetapi bebas antara satu sama lain. Pintasan papan kekunci sahaja tidak secara automatik memberikan alternatif penuding tunggal kepada pengguna yang boleh mengklik atau mengetik tetapi tidak boleh menahan dan menyeret. Kawalan Alih ke atas, Alih ke bawah, atau Alih ke yang kelihatan boleh memenuhi kedua-dua laluan input.
Isyarat ketiga ialah disiplin keadaan interaksi. Jawapan yang mantap membezakan keadaan melahu (idle), susun semula aktif, komit, dan batal; mengekalkan susunan asal untuk pengembalian semula (rollback); mengendalikan pointercancel, Escape, dan pelepasan tidak sah; serta tidak mengekalkan setiap kedudukan hover sebagai kemas kini perniagaan.
Isyarat keempat ialah tingkah laku teknologi bantuan. Semantik senarai dan butang natif, pemegang seret (drag handle) yang jelas, arahan ringkas, fokus yang stabil, pengumuman status yang sopan (polite), dan penunjuk pelepas yang kelihatan lebih penting daripada menambah banyak atribut ARIA. aria-grabbed dan aria-dropeffect telah ditolak penggunaannya (deprecated) dan tidak boleh dipersembahkan sebagai penyelesaian.
Akhir sekali, penemu duga mencari pengesahan berasaskan bukti: ujian susun semula tulen, ujian tetikus dan sentuhan, operasi papan kekunci sahaja, semakan pembaca skrin, asersi fokus, tingkah laku pergerakan dikurangkan (reduced-motion) dan warna dipaksa (forced-colors), serta pemulihan kegagalan simpan. Imbasan kebolehcapaian automatik tidak dapat membuktikan bahawa aliran susun semula yang dituturkan boleh difahami.
Soalan untuk Dijelaskan Sebelum Menjawab
- Adakah penyusunan semula dalam satu senarai atau antara senarai? Satu senarai memerlukan kedudukan akhir; pergerakan rentas senarai juga memerlukan pemilikan sumber dan destinasi, jenis pelepas yang dibenarkan, dan kemas kini atomik.
- Adakah susunan mesti disimpan secara jarak jauh (remote)? Susunan setempat sahaja boleh dikomit serta-merta. Penyimpanan jarak jauh memerlukan tingkah laku belum selesai (pending), berjaya, gagal, cuba semula, dan konflik versi.
- Input manakah yang berada dalam skop? Peristiwa seret HTML tetikus sahaja tidak mencukupi jika pengguna sentuhan, papan kekunci, suis, suara, atau pembaca skrin diperlukan.
- Adakah alternatif klik atau ketik kelihatan? Pintasan papan kekunci memenuhi keperluan yang berbeza. Untuk senarai boleh susun yang tidak kritikal, sediakan kawalan yang boleh diaktifkan dengan satu penuding tanpa menahan dan menggerakkannya.
- Adakah pratonton pergerakan dipaparkan serta-merta atau hanya semasa pelepas? Pratonton langsung memberikan maklum balas visual yang lebih kukuh, tetapi pembatalan mesti memulihkan susunan asal dan pengumuman tidak boleh berceloteh pada setiap piksel penuding.
- Bolehkah beberapa item dipilih? Pergerakan berbilang item mengubah model daripada satu ID item kepada set tersusun dan memerlukan peraturan untuk item boleh alih dan terkunci yang bercampur.
- Adakah senarai tersebut divirtualisasikan? Kedudukan di luar skrin tidak wujud sebagai sasaran pelepas DOM, jadi ujian perlanggaran (hit testing), pengumuman, jumlah kiraan, dan pergerakan papan kekunci mesti beroperasi pada model data.
- Bolehkah klien lain menyusun semula secara serentak? Jika ya, kontrak simpanan memerlukan versi senarai atau prasyarat yang setara dan dasar konflik yang jelas.
Rangka Kerja Jawapan 30 Saat
“Saya akan memodelkan susun semula sebagai satu arahan tulen: alihkan ID item yang stabil ke indeks akhir. Penyeretan penuding, tindakan papan kekunci, dan butang Alih yang kelihatan semuanya memanggilnya. Saya akan menggunakan semantik senarai dan butang natif, mengekalkan fokus pada pemegang yang dialihkan, dan mengumumkan kedudukan baharunya. Sesi menyimpan susunan asal, jadi Escape, pointercancel, pelepas tidak sah, atau kegagalan penyimpanan boleh memulihkannya. Kemudian saya akan mengesahkan invarian pilih atur dan menguji tetikus, sentuhan, kawalan klik sahaja, papan kekunci, pembaca skrin, fokus, dan aliran kegagalan.”
Analisis Mendalam Langkah demi Langkah
Mulakan dengan satu operasi data kanonikal. Input menggunakan ID stabil dan indeks akhir berasaskan sifar; outputnya ialah susunan baharu. Operasi mesti mengekalkan setiap ID tepat sekali dan membiarkan tatasusunan input tidak disentuh.
interface SortableItem {
id: string
label: string
}
function moveItem(
items: ReadonlyArray<SortableItem>,
itemId: string,
targetIndex: number,
): ReadonlyArray<SortableItem> {
const fromIndex = items.findIndex((item) => item.id === itemId)
if (fromIndex === -1 || items.length < 2) return items
const finalIndex = Math.max(0, Math.min(targetIndex, items.length - 1))
if (fromIndex === finalIndex) return items
const next = [...items]
const [movedItem] = next.splice(fromIndex, 1)
if (!movedItem) return items
next.splice(finalIndex, 0, movedItem)
return next
}Arahan ini menggunakan masa O(n) dan ruang O(n) kerana pembuangan, pemasukan, dan penyalinan tatasusunan menggeser item. Itu sesuai untuk senarai tugas biasa yang dirender sepenuhnya. Senarai maya yang sangat besar mungkin menyimpan kekunci pangkat boleh susun atau menggunakan pergerakan sisi pelayan mengikut ID bersebelahan, tetapi kerumitan tambahan itu memerlukan bukti daripada keperluan skala.
Gunakan ID yang stabil sebagai kekunci React. Dengan key={item.id}, React boleh mengalihkan nod item sedia ada dan bukannya menganggap indeks baharu sebagai identiti baharu. Ini membantu mengekalkan pemegang yang difokuskan dan keadaan item setempat. Jika kemas kini tak segerak masih kehilangan fokus, simpan rujukan (refs) yang berkekuncikan ID item dan pulihkan fokus ke pemegang yang sama selepas render yang dikomit. Jangan hantar fokus ke permulaan senarai, dan jangan paksa perubahan fokus untuk pengguna penuding.
Jadikan markup asas boleh difahami tanpa seretan. Senarai teratur dan item senarai mendedahkan struktur koleksi. Setiap item mempunyai butang natif yang dinamakan, contohnya, “Reorder Review.” Sediakan butang Alih ke atas dan Alih ke bawah yang kelihatan, atau tindakan Alih ke kedudukan, dengan nama item disertakan dalam setiap nama yang boleh diakses. Nyahdayakan tindakan sempadan yang mustahil. Kawalan ini berfungsi melalui klik, ketik, dan pengaktifan papan kekunci, jadi ia merupakan alternatif yang mudah ditemui dan laluan pemulihan yang mudah apabila seretan gagal.
Perbezaan antara dua keperluan kekebolehcapaian mengubah reka bentuk. Operasi papan kekunci bermakna susun semula yang lengkap boleh dilakukan tanpa peranti penuding. Secara berasingan, pergerakan menyeret mesti mempunyai kaedah penuding tunggal yang tidak memerlukan tindakan menahan dan menggerakkan penuding apabila penyeretan tidak penting. Mod seret kekunci anak panah boleh memuaskan pengguna papan kekunci tetapi tidak memenuhi keperluan kedua melainkan kawalannya juga boleh dikendalikan melalui klik atau ketik. Butang pergerakan yang kelihatan memuaskan kedua-duanya.
Mod seret papan kekunci padat pilihan boleh mengurangkan tekanan kekunci Tab berulang kali. Fokuskan pemegang seret dan tekan Enter atau Space untuk bermula; Anak Panah Atas dan Anak Panah Bawah menukar kedudukan calon; Enter atau Space mengkomit; Escape membatalkan dan memulihkan snapshot. Letakkan arahan ini dalam teks yang dirujuk oleh pemegang supaya pengguna boleh mengetahuinya. Jika item tersebut juga menyokong pemilihan, pastikan arahan pemilihan dan susun semula berasingan supaya Space tidak mempunyai dua makna pada sasaran fokus yang sama.
Wakilkan interaksi sebagai sesi jangka pendek. Semasa bermula, simpan itemId, jenis input, susunan asal, dan indeks calon semasa. Pergerakan penuding atau papan kekunci hanya mengemas kini calon melalui moveItem. Komit menghasilkan satu permintaan penyimpanan dan satu pengumuman. Batal memulihkan susunan asal dan mengumumkan pembatalan. Respons pelayan baharu tidak boleh dibenarkan untuk menulis ganti sesi yang lebih baharu semata-mata kerana permintaannya selesai kemudian.
Untuk input penuding, gunakan pemegang eksplisit dan bukannya menjadikan seluruh baris boleh diseret. Ini menghalang seretan daripada mencuri klik daripada pautan, kotak pilihan, pemilihan teks, atau penatalan. Jika melaksanakan penyusunan dalam halaman dengan Pointer Events, tunggu ambang pergerakan kecil, tangkap penuding (capture the pointer), kira kedudukan calon daripada titik tengah item, dedahkan penunjuk pemasukan bukan warna sahaja, dan kendalikan pointerup, pointercancel, tangkapan hilang, penatalan, dan pelepasan di luar senarai. Pustaka seret yang teruji lebih disukai apabila penderia sentuhan, autotatal, pengesanan perlanggaran, bekas tatal bersarang, dan tingkah laku teknologi bantuan semuanya merupakan keperluan.
Seret dan lepas HTML natif mungkin munasabah untuk pemindahan data desktop atau rentas aplikasi, tetapi ia tidak menyediakan aliran kerja susun semula papan kekunci atau pembaca skrin. Model peristiwanya juga memerlukan sasaran pelepas sah yang eksplisit dan menyekat peristiwa input peranti lain semasa penyeretan. Memilihnya tidak membuang keperluan untuk kawalan alih, tingkah laku fokus, pengumuman, atau pengesahan sentuhan.
Sampaikan hasil melalui visual dan semantik. Tunjukkan titik pemasukan calon dengan bentuk atau sempadan di samping warna, kekalkan penunjuk fokus yang kelihatan, dan hormati keutamaan pergerakan dikurangkan. Gunakan kawasan status sopan yang kekal untuk mesej pendek selepas pergerakan papan kekunci yang disengajakan, komit, batal, dan kegagalan. Mesej seperti “Moved Review to position 2 of 5” membawa maklumat item, hasil, kedudukan, dan jumlah keseluruhan. Jangan umumkan setiap hover penuding, dan jangan cipta semula kawasan langsung (live region) pada masa yang sama dengan mesejnya.
Elakkan semantik seret yang lapuk. WAI-ARIA 1.2 menandakan aria-grabbed dan aria-dropeffect sebagai ditolak penggunaannya. Elemen natif, nama boleh diakses, arahan deskriptif, keadaan semasa yang disampaikan dalam teks, dan pengumuman yang diuji menyediakan kontrak yang lebih boleh dipercayai. ARIA tidak menambah tingkah laku papan kekunci yang hilang atau alternatif klik yang tiada.
Untuk penyimpanan jarak jauh, hantar ID tersusun yang stabil atau arahan alih berserta versi yang diedit oleh klien. Pratonton hasil secara optimistik, dedahkan keadaan penyimpanan tanpa menyekat fokus papan kekunci, dan komit pengumuman hanya di bawah peraturan produk yang dipilih. Pada kegagalan rangkaian, sama ada kekalkan susunan belum selesai setempat dengan Cuba Semula atau kembali ke snapshot dan umumkan pengembalian semula tersebut. Pada konflik versi, ambil susunan semasa dan minta pengguna mencuba semula atau gunakan penggabungan yang ditetapkan; menulis ganti susunan klien lain secara senyap bukanlah strategi pemulihan.
Pengesahan bermula dengan arahan tulen. Uji pergerakan pertama, terakhir, bersebelahan, kedudukan sama, ID tidak diketahui, dan luar julat. Untuk input yang dijana, pastikan output mengandungi ID yang sama dengan kiraan yang sama dan hanya pergerakan relatif yang diminta. Kemudian jalankan matriks interaksi:
- seretan tetikus, seretan sentuhan, kawalan klik sahaja, dan pelepas di luar senarai;
- pergerakan papan kekunci sahaja, komit, tindakan sempadan, dan pembatalan Escape;
- fokus kekal pada pemegang item yang dialihkan selepas setiap render dan pengembalian semula;
- VoiceOver dengan Safari dan NVDA dengan Firefox atau Chrome mengumumkan item, arahan, kedudukan baharu, pembatalan, dan kegagalan penyimpanan sekali;
- zum 200%, warna dipaksa, kontras tinggi, pergerakan dikurangkan, label panjang, penatalan, dan reka letak RTL;
- kejayaan tertangguh, penyusunan semula permintaan, kegagalan luar talian, cuba semula, dan konflik versi.
Alat kebolehcapaian automatik boleh mengesan nama yang hilang, atribut tidak sah, dan beberapa masalah kebolehfokusan. Ia tidak dapat menilai sama ada model papan kekunci mudah ditemui, sama ada urutan yang dituturkan koheren, atau sama ada pembaca skrin skrin sentuh boleh menyelesaikan tugas tersebut. Perkara tersebut memerlukan penggunaan manual.
Contoh Jawapan Berkualiti Tinggi
“Saya akan memastikan identiti item bebas daripada kedudukan tatasusunan. Reducer menerima ID item dan indeks akhir, mengembalikan pilih atur baharu, dan merupakan satu-satunya kod yang dibenarkan untuk menukar susunan. Penyeretan penuding, butang Alih ke atas atau Alih ke bawah, dan sebarang mod seret papan kekunci semuanya menghantar arahan yang sama.
Garis dasar semantik ialah senarai teratur dengan butang natif. Setiap baris mempunyai pemegang susun semula eksplisit dan kawalan pergerakan kelihatan yang nama boleh diaksesnya merangkumi label item. Kawalan pergerakan penting kerana sokongan papan kekunci dan alternatif klik atau ketik untuk penyeretan adalah keperluan yang berasingan. Saya tidak akan bergantung pada aria-grabbed atau aria-dropeffect; kedua-duanya telah ditolak penggunaannya.
Apabila susun semula bermula, saya menyimpan susunan asal dan ID item aktif. Ujian perlanggaran penuding atau kekunci anak panah hanya mengemas kini kedudukan calon. Komit menghantar satu simpanan dan mengumumkan, contohnya, ‘Moved Review to position 2 of 5.’ Escape, pointercancel, pelepas tidak sah, atau peraturan kegagalan simpan yang dipilih memulihkan snapshot. Kekunci React yang stabil memastikan pemegang yang sama kekal difokuskan selepas susunan DOM berubah.
Untuk penyusunan penuding, saya akan menggunakan pemegang khusus, ambang pergerakan, tangkapan penuding, penunjuk pemasukan yang jelas, tingkah laku autotatal, dan pembersihan pembatalan. Jika sentuhan, penatalan bersarang, dan pengendalian perlanggaran rentas pelayar diperlukan, saya akan memilih pustaka yang diuji hanya selepas menyemak tingkah laku papan kekunci dan pembaca skrinnya; demo tetikus sahaja tidak mencukupi.
Saya akan menguji unit invarian pilih atur dan kemudian menyelesaikan tugas secara manual menggunakan tetikus, sentuhan, papan kekunci, kawalan klik sahaja, VoiceOver, dan NVDA. Saya juga akan menguji fokus, Escape, pelepas di luar, pergerakan dikurangkan, warna dipaksa, simpanan tertangguh, respons lapuk, dan konflik versi. Itu mengesahkan kontrak interaksi sebenar; imbasan automatik sahaja tidak mencukupi.”
Kesilapan Biasa
- Menggunakan indeks tatasusunan sebagai kekunci → penyusunan semula mengubah identiti, fokus, dan keadaan setempat item → Gunakan ID item yang stabil untuk kekunci dan arahan.
- Menjadikan seret sebagai satu-satunya interaksi → pengguna yang tidak boleh menahan dan menggerakkan penuding tidak boleh menyusun semula → Sediakan kawalan klik atau ketik yang kelihatan dengan hasil yang setara.
- Menambah kekunci anak panah dan mendakwa semua keperluan dipenuhi → kesetaraan papan kekunci sahaja mungkin masih kekurangan kaedah penuding tunggal tanpa seretan → Nilai keperluan papan kekunci dan pergerakan menyeret secara berasingan.
- Melampirkan pendengar seret pada seluruh baris → pautan, pemilihan, kotak pilihan, dan penatalan berkonflik dengan susun semula → Gunakan pemegang boleh fokus yang eksplisit.
- Melaksanakan algoritma susun semula yang berasingan untuk setiap input → tetikus, sentuhan, dan papan kekunci menghasilkan kes pinggir yang berbeza → Halakan setiap input ke satu arahan ID stabil.
- Memutasi tatasusunan atau DOM secara langsung → keadaan yang dirender dan keadaan yang disimpan menyimpang → Kembalikan pilih atur baharu daripada pemilik keadaan.
- Menggunakan
aria-grabbeddanaria-dropeffectsebagai pelan kebolehcapaian → atribut tersebut telah ditolak penggunaannya dan tidak menambah interaksi → Gunakan kawalan natif, arahan, keadaan, fokus, dan pengumuman yang diuji. - Mengumumkan setiap pergerakan penuding → kawasan langsung menjadi bising dan tertangguh → Umumkan langkah papan kekunci yang disengajakan dan hasil akhir, bukan piksel penuding.
- Mengalihkan fokus ke permulaan senarai selepas susun semula → pengguna kehilangan kedudukan mereka → Kekalkan atau pulihkan fokus mengikut ID item yang stabil.
- Menyimpan setiap kedudukan hover → perlumbaan rangkaian (network races) boleh menggunakan susunan perantaraan yang lapuk → Simpan satu pergerakan yang dikomit dengan prasyarat versi.
- Hanya bergantung pada audit automatik → ia tidak dapat mengesahkan arahan yang dituturkan atau aliran input yang lengkap → Uji dengan papan kekunci sebenar, sentuhan, dan pembaca skrin.
Soalan Susulan dan Respons
Susulan 1: Apakah yang berubah apabila senarai divirtualisasikan?
Jangan anggap baris DOM yang dilekapkan sebagai koleksi yang lengkap. Kekalkan pergerakan, jumlah kiraan, dan kedudukan calon dalam model data. Arahan papan kekunci boleh bergerak mengikut indeks logik walaupun destinasinya berada di luar skrin, kemudian tatal item yang dialihkan ke dalam paparan tanpa kehilangan sasaran fokusnya. Pergerakan penuding memerlukan ujian perlanggaran dan autotatal yang menyedari model. Jika pustaka tidak dapat mendedahkan semantik koleksi yang tepat atau fokus yang stabil melalui virtualisasi, mod boleh diakses bukan maya mungkin merupakan pertukaran (trade-off) yang lebih selamat pada skala yang diukur.
Susulan 2: Bagaimanakah anda akan mengalihkan beberapa item yang dipilih?
Simpan set tersusun ID stabil, kekalkan susunan relatifnya, buang ia sebagai satu kumpulan, dan masukkan kumpulan tersebut pada satu sempadan akhir. Pengumuman merangkumi kiraan item dan destinasi. Pemilihan dan pemegang seret memerlukan arahan yang berasingan, terutamanya apabila Space sudah menogol pemilihan. Tolak pemilihan bercampur yang mengandungi item terkunci atau tentukan dengan tepat item mana yang kekal; memindahkan sebahagian daripada pemilihan secara senyap adalah kabur.
Susulan 3: Bagaimana jika dua klien menyusun semula senarai yang sama secara serentak?
Lampirkan versi senarai atau ETag pada permintaan alih. Pelayan menerima pergerakan hanya jika versi sepadan. Pada konflik, ambil susunan semasa, kekalkan item dan destinasi yang dimaksudkan oleh pengguna sebagai konteks, dan tawarkan percubaan semula atau gunakan peraturan penggabungan yang didokumenkan. Last-write-wins hanya boleh diterima apabila produk secara eksplisit menerima kehilangan keputusan susunan pengguna lain.
Susulan 4: Adakah anda akan menggunakan seret dan lepas HTML natif, Pointer Events, atau pustaka?
Seret dan lepas natif berguna untuk desktop dan pemindahan data luaran, tetapi ia tidak menyediakan aliran kerja papan kekunci dan teknologi bantuan yang lengkap. Pointer Events menawarkan kawalan untuk penyusunan sentuhan dan tetikus dalam halaman tetapi memerlukan pengesanan perlanggaran, tangkapan, autotatal, dan pembersihan. Pustaka ialah pilihan terbaik apabila tingkah laku tersebut telah pun diuji, dengan syarat papan kekunci sebenar, pembaca skrin skrin sentuh, fokus, dan semantik DOM melepasi matriks pengesahan produk. Kawalan pergerakan dan arahan susun semula kanonikal kekal tidak kira pilihan penderia.
Susulan 5: Bagaimana jika penyimpanan gagal selepas pengguna terus bekerja?
Tag setiap susun semula yang dikomit dengan jujukan klien dan versi pelayan yang menjadi asasnya. Kegagalan lewat hanya boleh mengembalikan keadaan yang diperoleh daripada permintaan tersebut; ia tidak boleh menggantikan susunan baharu yang disahkan dengan snapshot lama. Dasar selamat yang paling mudah ialah menyirikan (serialize) simpanan, mengekalkan satu susunan eksplisit yang belum selesai, dan menyekat komit kedua sambil membenarkan fokus dan pembacaan. Barisan gilir yang lebih responsif memerlukan ujian pemangkalan semula (rebasing) dan konflik sebelum ia wajar digunakan.