jQuery anak pertama dari "ini"

317

Saya mencoba meneruskan "ini" dari rentang yang diklik ke fungsi jQuery yang kemudian dapat mengeksekusi jQuery pada anak pertama elemen yang diklik itu. Tampaknya tidak bisa melakukannya dengan benar ...

<p onclick="toggleSection($(this));"><span class="redClass"></span></p>

Javascript:

function toggleSection(element) {
  element.toggleClass("redClass");
}

Bagaimana cara merujuk: elemen pertama-anak?

macca1
sumber
4
Jika Anda menggunakan jQuery, mengapa Anda tidak mengikat event handler menggunakan jQuery juga?
Vivin Paliath
2
karena pengikat event bind harus diinisialisasi dalam document.ready () yang menambahkan hit performa (ini adalah aplikasi untuk IE6). Atau ada cara lain?
macca1
Hm .. tidak yakin. Mengikat menggunakan jQuery adalah cara standar (jika Anda sudah menggunakan jQuery). Kinerja seperti apa yang Anda alami saat menggunakan jQuery(document).ready(...)?
Vivin Paliath
Ini adalah aplikasi besar dengan 7+ pengembang. Awalnya 4+ detik sebelum saya mencoba membersihkannya sedikit. Jadi saya lebih suka menghindari menambahkan lebih banyak ketika saya tidak perlu :)
macca1

Jawaban:

482

Jika Anda ingin menerapkan pemilih ke konteks yang disediakan oleh set jQuery yang ada, coba fungsi find () :

element.find(">:first-child").toggleClass("redClass");

Jørn Schou-Rode mencatat bahwa Anda mungkin hanya ingin menemukan turunan langsung pertama dari elemen konteks, karenanya pemilih anak (>). Dia juga menunjukkan bahwa Anda bisa menggunakan fungsi children () , yang sangat mirip dengan find () tetapi hanya mencari satu level di dalam hierarki (yang Anda butuhkan ...):

element.children(":first").toggleClass("redClass");
Shog9
sumber
1
Terima kasih! bekerja dengan sempurna. Saya membayangkan cara lain yang tercantum di bawah ini akan berfungsi juga.
macca1
6
Saya percaya find()pencarian melalui semua keturunan, dan :first-childdapat mencocokkan satu elemen per orang tua. Karenanya, kueri ini kemungkinan akan mengembalikan beberapa elemen. Atau saya salah?
Jørn Schou-Rode
19
Saya tahu ini adalah pertanyaan / jawaban lama, tetapi penggunaan pemilih ">" tanpa orangtua dalam pemilih itu disusutkan (misalnya, ">: anak pertama") pada jQuery 1.8. Saya sarankan sebagai gantinya menggunakan element.children(":first-child")atauelement.children().first();
Kevin B
3
@KevinB rupanya mereka memutuskan untuk tidak mencela semuanya
Alnitak
1
pendekatan terbaik adalah BUKAN untuk mengulangi semua item dan kemudian memilih yang pertama, seperti yang disarankan di sini. Ini akan menjadi BURUK.
vsync
74

Gunakan childrenfungsi dengan :firstpemilih untuk mendapatkan anak pertama tunggal dari element:

element.children(":first").toggleClass("redClass");
Jørn Schou-Rode
sumber
element.children () [0] .toggleClass ("redClass");
Zakos
5
@ Zakos:TypeError: Object [object HTMLAnchorElement] has no method 'toggleClass'
Jørn Schou-Rode
51

Saya telah menambahkan tes jsperf untuk melihat perbedaan kecepatan untuk berbagai pendekatan untuk mendapatkan anak pertama (total 1000+ anak)

diberikan, notif = $('#foo')

Cara jQuery:

  1. $(":first-child", notif) - 4.304 ops / dtk - tercepat
  2. notif.children(":first") - 653 ops / detik - 85% lebih lambat
  3. notif.children()[0] - 1.416 ops / detik - 67% lebih lambat

Cara asli:

  1. JavaScript asli ' ele.firstChild- 4,934,323 ops / detik (semua pendekatan di atas 100% lebih lambat dibandingkan dengan firstChild)
  2. Elemen DOM asli dari jQery: notif[0].firstChild- 4,913.658 ops / dtk

Jadi, 3 pendekatan jQuery pertama tidak dianjurkan, setidaknya untuk anak pertama (saya ragu itu akan menjadi masalah dengan banyak lainnya juga). Jika Anda memiliki objek jQuery dan perlu mendapatkan anak pertama, maka dapatkan elemen DOM asli dari objek jQuery, menggunakan referensi array [0] (disarankan) atau .get(0)dan gunakan ele.firstChild. Ini memberikan hasil yang sama identik dengan penggunaan JavaScript biasa.

semua tes dilakukan di Chrome Canary build v15.0.854.0

manikanta
sumber
20
Sebenarnya, firstChildtidak akan memberikan hasil yang sama dengan children()kueri jQuery atau pemilih. firstChildakan menyertakan simpul teks yang jarang diinginkan. contents()Fungsi jQuery akan memasukkan mereka, tetapi children()tidak akan. Dukungan browser firstElementChildyang lebih baru yang akan memberikan elemen anak pertama, tetapi IE <9 tidak mendukungnya. Jadi, jika Anda menggunakan firstChildAnda harus secara manual menemukan anak simpul non-teks pertama.
Maks
1
$(":first-child", notif)harus $(":first", notif)untuk perilaku yang diharapkan. Yang pertama akan mengembalikan semua keturunan elemen anak pertama.
Drazen Bjelovuk
18
element.children().first();

Temukan semua anak dan dapatkan yang pertama dari mereka.

Bishal Paudel
sumber
1
Sejauh ini metode yang paling sederhana, dan lebih efisien daripada .children(':first').
Gras Double
3
Bagaimana ini lebih efisien? Tampaknya itu mendapatkan semua anak, lalu mengambil yang pertama, versus hanya mendapatkan anak pertama.
Anthony McGrath
9

Sudahkah Anda mencoba

$(":first-child", element).toggleClass("redClass");

Saya pikir Anda ingin mengatur elemen Anda sebagai konteks untuk pencarian Anda. Mungkin ada cara yang lebih baik untuk melakukan ini dimana beberapa guru jQuery lain akan melompat ke sini dan membuang Anda :)

theIV
sumber
3
ini akan gagal jika elementmemiliki cucu
Alnitak
4

Saya baru saja menulis sebuah plugin yang menggunakan .firstElementChildjika memungkinkan, dan kembali ke iterasi setiap node individu jika perlu:

(function ($) {
    var useElementChild = ('firstElementChild' in document.createElement('div'));

    $.fn.firstChild = function () {
        return this.map(function() {
            if (useElementChild) {
                return this.firstElementChild;
            } else {
                var node = this.firstChild;
                while (node) {
                    if (node.type === 1) {
                        break;
                    }
                    node = node.nextSibling;
                }
                return node;
            }
        });
    };
})(jQuery);

Ini tidak secepat solusi DOM murni, tetapi dalam uji jsperf di bawah Chrome 24 itu beberapa urutan besarnya lebih cepat daripada metode berbasis pemilih jQuery lainnya.

Alnitak
sumber
1
Saya suka plugin ini - tetapi ada 2 masalah: 1) Script plugin tidak dapat dimasukkan di kepala karena document.bodybelum diinisialisasi, 2) Kinerja hanya jauh lebih baik daripada alternatif jika jumlah node anak sangat tinggi. Untuk hanya beberapa anak (katakanlah kurang dari 10) $('>:first-child',context)itu sedikit lebih cepat. Hanya jumlah anak yang memengaruhi kinerja, bukan kedalaman.
codefactor
@codefactor poin bagus tentang document.body- Saya akan memeriksanya.
Alnitak
4

Anda bisa menggunakan DOM

$(this).children().first()
// is equivalent to
$(this.firstChild)
Yukulélé
sumber
1

tolong gunakan ini seperti hal pertama ini beri nama kelas untuk menandai p seperti "myp"

kemudian gunakan kode berikut

$(document).ready(function() {
    $(".myp").click(function() {
        $(this).children(":first").toggleClass("classname"); // this will access the span.
    })
})
vishal gupta
sumber
-3

Jika Anda ingin anak pertama yang Anda butuhkan

    $(element).first();

Jika Anda ingin elemen pertama tertentu dalam dom dari elemen Anda, gunakan di bawah ini

    var spanElement = $(elementId).find(".redClass :first");
    $(spanElement).addClass("yourClassHere");

coba: http://jsfiddle.net/vgGbc/2/

Amit Rathod
sumber
11
ini hanya salah - jika elementmerupakan simpul DOM maka $(element).first()sama dengan $(element), bukan anak pertamanya.
Alnitak
1
Setuju, jika elemen adalah simpul DOM $ (elemen) .pertama () adalah $ yang setara (elemen) ini menyebabkan saya bermasalah dengan knockoutJS binding
drgn