Saya bisa melakukan ini:
<div id="myDiv">
<div class="foo"></div>
</div>
myDiv = getElementById("myDiv");
myDiv.querySelectorAll("#myDiv > .foo");
Artinya, saya berhasil mengambil semua turunan langsung dari myDiv
elemen yang memiliki kelas .foo
.
Masalahnya, saya merasa terganggu karena saya harus menyertakan #myDiv
in dalam selector, karena saya menjalankan kueri pada myDiv
elemen (jadi jelas berlebihan).
Saya seharusnya bisa membiarkan #myDiv
off, tapi kemudian selector bukan sintaks hukum karena dimulai dengan a >
.
Adakah yang tahu cara menulis selector yang hanya mendapatkan turunan langsung dari elemen yang dijalankan oleh selector?
javascript
dom
css-selectors
mattsh
sumber
sumber
Jawaban:
Pertanyaan bagus. Pada saat diminta, cara yang diterapkan secara universal untuk melakukan "kueri yang di-rooting kombinator" (sebagaimana John Resig menyebutnya ) tidak ada.
Sekarang pseudo-class : scope telah diperkenalkan. Ini tidak didukung pada Edge atau IE versi [pra-Chrominum], tetapi telah didukung oleh Safari selama beberapa tahun. Dengan menggunakan itu, kode Anda bisa menjadi:
Perhatikan bahwa dalam beberapa kasus Anda juga dapat melewati
.querySelectorAll
dan menggunakan fitur API DOM model lama yang bagus. Misalnya sajamyDiv.querySelectorAll(":scope > *")
Anda bisa langsung menulismyDiv.children
, misalnya.Sebaliknya, jika Anda belum dapat mengandalkan
:scope
, saya tidak dapat memikirkan cara lain untuk menangani situasi Anda tanpa menambahkan lebih banyak logika filter khusus (misalnya, temukanmyDiv.getElementsByClassName("foo")
siapa.parentNode === myDiv
), dan jelas tidak ideal jika Anda mencoba mendukung satu jalur kode yang benar-benar hanya ingin mengambil string pemilih arbitrer sebagai masukan dan daftar kecocokan sebagai keluaran! Tetapi jika seperti saya, Anda akhirnya menanyakan pertanyaan ini hanya karena Anda terjebak berpikir "yang Anda miliki hanyalah palu" jangan lupa ada berbagai alat lain yang ditawarkan DOM juga.sumber
myDiv.getElementsByClassName("foo")
tidak sama denganmyDiv.querySelectorAll("> .foo")
, itu lebih sepertimyDiv.querySelectorAll(".foo")
(yang sebenarnya bekerja dengan cara) di mana ia menemukan semua keturunan.foo
bukan hanya anak-anak.<style scoped>
) tidak ada hubungannya dengan:scope
pseudo-selector yang dijelaskan dalam jawaban ini.Cara yang benar untuk menulis pemilih yang "di-root" ke elemen saat ini adalah dengan menggunakan
:scope
.Namun, dukungan browser terbatas dan Anda memerlukan shim jika ingin menggunakannya. Saya membuat scopedQuerySelectorShim untuk tujuan ini.
sumber
:scope
spesifikasi saat ini adalah "Draf Kerja" dan karena itu dapat berubah. Kemungkinannya masih akan berfungsi seperti ini jika / ketika diadopsi, tetapi agak dini untuk mengatakan ini adalah "cara yang benar" untuk melakukannya menurut saya.Berikut adalah metode fleksibel, ditulis dalam vanilla JS, yang memungkinkan Anda menjalankan kueri pemilih CSS hanya pada turunan langsung dari suatu elemen:
sumber
Math.random().toString(36).substr(2, 10)
menghasilkan token yang sama lebih dari sekali.any dupe would need to also be a child of the same parent node
,id
atribut di seluruh dokumen. Anda benar kemungkinan masih cukup kecil, tapi terima kasih telah mengambil jalan yang bagus dan menambahkan penghitung itu :)jika Anda tahu pasti elemennya unik (seperti kasus Anda dengan ID):
Untuk solusi yang lebih "global": (gunakan shim matchSelector )
di mana
elm
elemen induk Anda, dansel
adalah pemilih Anda. Bisa juga digunakan sebagai prototipe.sumber
matchesSelector
uncrefixed (yang bahkan tidak berfungsi di versi terbaru Chrome), mencemari namespace global (ret tidak dideklarasikan), tidak mengembalikan NodeList seperti yang diharapkan dari querySelectorMethods. Menurut saya ini bukan solusi yang baik, karena itu suara negatifnya.Solusi berikut berbeda dengan yang diusulkan sejauh ini, dan berhasil untuk saya.
Alasannya adalah Anda memilih semua turunan yang cocok terlebih dahulu, lalu menyaring yang bukan turunan langsung. Seorang anak adalah anak langsung jika tidak memiliki induk yang cocok dengan selektor yang sama.
HTH!
sumber
Saya membuat fungsi untuk menangani situasi ini, saya pikir saya akan membagikannya.
Intinya apa yang Anda lakukan adalah menghasilkan string acak (fungsi randomString di sini adalah modul npm yang diimpor, tetapi Anda dapat membuatnya sendiri.) Kemudian menggunakan string acak tersebut untuk menjamin bahwa Anda mendapatkan elemen yang Anda harapkan di selektor. Maka Anda bebas menggunakan
>
setelah itu.Alasan saya tidak menggunakan atribut id adalah karena atribut id mungkin sudah digunakan dan saya tidak ingin menimpanya.
sumber
Kita bisa dengan mudah mendapatkan semua turunan langsung dari sebuah elemen menggunakan
childNodes
dan kita bisa memilih leluhur dengan kelas tertentuquerySelectorAll
, jadi tidak sulit membayangkan kita bisa membuat fungsi baru yang mendapatkan keduanya dan membandingkan keduanya.Catatan: Ini akan mengembalikan Array of Nodes, bukan NodeList.
Pemakaian
sumber
Saya ingin menambahkan bahwa Anda dapat memperluas kompatibilitas : scope dengan hanya menetapkan atribut sementara ke simpul saat ini.
sumber
Saya akan pergi dengan
sumber
Saya hanya melakukan ini tanpa mencobanya. Apakah ini akan berhasil?
Cobalah, mungkin berhasil mungkin tidak. Apolovies, tapi saya tidak menggunakan komputer sekarang untuk mencobanya (menanggapi dari iPhone saya).
sumber