JQuery .each () ย้อนกลับ


442

ฉันใช้ JQuery เพื่อเลือกองค์ประกอบบางอย่างในหน้าหนึ่งจากนั้นเลื่อนไปรอบ ๆ ใน DOM ปัญหาที่ฉันมีคือฉันต้องเลือกองค์ประกอบทั้งหมดในลำดับย้อนกลับที่ JQuery ต้องการเลือกโดยธรรมชาติ ตัวอย่างเช่น:

<ul>
   <li>Item 1</li>
   <li>Item 2</li>
   <li>Item 3</li>
   <li>Item 4</li>
   <li>Item 5</li>
</ul>

ฉันต้องการเลือกรายการ li ทั้งหมดและใช้คำสั่ง. each () บนรายการ แต่ฉันต้องการเริ่มต้นด้วยรายการ 5 จากนั้นรายการ 4 เป็นต้นเป็นไปได้หรือไม่

คำตอบ:


681
$($("li").get().reverse()).each(function() { /* ... */ });

10
สิ่งสำคัญที่ควรทราบคือดัชนีจะไม่กลับด้านดังนั้นหากคุณต้องการทำเฉพาะสามครั้งล่าสุดเท่านั้นคุณไม่สามารถคาดหวังได้ว่า<li>Item 5</li>จะมีดัชนีเป็น 0
ผู้เบิกทาง

8
ถึง David Andres: คุณอาจลืมเพิ่ม $ () ก่อนหน้า li ฉันทำผิดพลาดและได้รับ "ไม่ได้กำหนด func"
Michal - wereda-net

2
@DavidAndres: คุณพลาด.get()ที่จะเปลี่ยนอาร์เรย์ที่ห่อ jQuery ไปเป็นอาร์เรย์ JS ธรรมดา JS .reverse()อาร์เรย์มี
ซ้อนกัน

1
ข้อควรระวัง: Array.reverse()ทั้งสองปรับเปลี่ยนอาร์เรย์ในสถานที่และส่งกลับอาร์เรย์กลับ ดังนั้นวิธีการแก้ปัญหานี้อาศัย $ (). get () กลับอาร์เรย์ใหม่และไม่อ้างอิงถึงบาง jQuery ภายในหรืออาร์เรย์ DOM อาจเป็นการเดิมพันที่ปลอดภัยภายในขอบเขตของตัวอย่างนี้ Caveat Coder
Bob Stein

404

ฉันขอเสนอวิธีที่สะอาดที่สุดให้คุณในรูปแบบของปลั๊กอิน jquery ที่เล็กที่สุดในโลก:

jQuery.fn.reverse = [].reverse;

การใช้งาน:

$('jquery-selectors-go-here').reverse().each(function () {
    //business as usual goes here
});

- มอบเครดิตทั้งหมดให้กับ Michael Geary ในโพสต์ของเขาที่นี่: http://www.mail-archive.com/discuss@jquery.com/msg04261.html


ตกลงฉันเห็นด้วยที่เท่ห์ แต่ทำไมมันถึงใช้งานได้ คุณกำลังคัดลอก (พูดอย่างหลวม ๆ ) Array.prototype.reverse กับ jQuery.prototype.reverse และเมื่อมันถูกเรียกthisอ็อบเจกต์จะมีคุณสมบัติเป็นตัวเลขและคุณสมบัติความยาวดังนั้นจาวาสคริปต์สามารถทำดัชนีฟังก์ชันอาเรย์กับอินสแตนซ์ jQuery ได้หรือไม่?
mlhDev

5
สิ่งสำคัญที่ควรทราบคือดัชนีจะไม่กลับด้านดังนั้นหากคุณต้องการทำเฉพาะสามครั้งล่าสุดเท่านั้นคุณไม่สามารถคาดหวังได้ว่า<li>Item 5</li>จะมีดัชนีเป็น 0
ผู้เบิกทาง

1
@ Matthew - ใช่คุณเข้าใจถูกต้อง รหัสที่ไม่แน่นอนคัดลอกอ้างอิงที่จะไปArray.prototype.reverse jQuery.prototype.reverseเมธอดอาร์เรย์ JavaScript จำนวนมากจะทำงานได้ดีกับวัตถุใด ๆ ที่มีลักษณะเหมือนอาร์เรย์นั่นคือถ้าวัตถุนั้นมี.lengthคุณสมบัติและตัวเลขดัชนี reverseไม่ได้ขึ้นอยู่กับการแทนค่าภายในของอาเรย์ มันเข้าถึงอาร์เรย์โดยใช้ปกติ.length, [0], [1]ฯลฯ เช่นเดียวกับรหัสอาร์เรย์ที่คุณต้องการเขียนเอง
Michael Geary

8
มันไม่สิ้นเปลืองหรือไม่ที่จะยกตัวอย่าง Array ใหม่เพื่อรับreverseวิธี จะเร็วกว่าหรือที่จะคัดลอกการอ้างอิงไปยังฟังก์ชันArray.prototype.reverseเช่นjQuery.fn.reverse = Array.prototype.reverse;? ไม่สั้นและ "ฉลาด" แต่มีประสิทธิภาพมากกว่าหรือไม่ เป็นที่ยอมรับว่าอาจไม่สามารถสังเกตเห็นได้ในเบราว์เซอร์ที่เร็วที่สุดในวันนี้ แต่ยัง ...
zachelrath

3
@zachelrath ใช่ฉันไม่สามารถแยกความแตกต่างระหว่างผลลัพธ์ได้อีกต่อไป ดูเหมือนว่า 20% เป็นเพียงความบังเอิญ โปรดจำไว้ว่าคุณเพียงตั้งค่าฟังก์ชั่นหนึ่งครั้งดังนั้นการสร้างอินสแตนซ์จะเกิดขึ้นเพียงครั้งเดียวเท่านั้นจากนั้นฟังก์ชันจะถูกตั้งค่า
Sandy Gifford

64

คุณทำได้

jQuery.fn.reverse = function() {
    return this.pushStack(this.get().reverse(), arguments);
}; 

ติดตามโดย

$(selector).reverse().each(...) 

14
วิธีการนี้ถูกเสนอครั้งแรกโดยจอห์นเรซิก (นักพัฒนา jQuery) ในjQuery รายชื่อผู้รับจดหมาย
Chris Shouts

20

นี่คือตัวเลือกที่แตกต่างกันสำหรับสิ่งนี้:

ครั้งแรก : ไม่มี jQuery:

var lis = document.querySelectorAll('ul > li');
var contents = [].map.call(lis, function (li) {
    return li.innerHTML;
}).reverse().forEach(function (content, i) {
    lis[i].innerHTML = content;
});

ตัวอย่างที่นี่

... และด้วย jQuery:

คุณสามารถใช้สิ่งนี้:

$($("ul > li").get().reverse()).each(function (i) {
    $(this).text( 'Item ' + (++i));
});

ตัวอย่างที่นี่

อีกวิธีหนึ่งการใช้ jQuery กับreverseคือ:

$.fn.reverse = [].reverse;
$("ul > li").reverse().each(function (i) {
    $(this).text( 'Item ' + (++i));
});

สาธิตนี้ที่นี่

อีกทางเลือกหนึ่งคือการใช้length(จำนวนองค์ประกอบที่ตรงกับตัวเลือกนั้น) และลงไปจากที่นั่นโดยใช้การindexทำซ้ำแต่ละครั้ง จากนั้นคุณสามารถใช้สิ่งนี้:

var $li = $("ul > li");
$li.each(function (i) {
    $(this).text( 'Item ' + ($li.length - i));
});

การสาธิตนี้ที่นี่

อีกประเภทที่เกี่ยวข้องกับรายการด้านบน:

var $li = $("ul > li");
$li.text(function (i) {
    return 'Item ' + ($li.length - i);
});

ตัวอย่างที่นี่


14

ฉันชอบสร้างปลั๊กอินแบบย้อนกลับเช่น

jQuery.fn.reverse = function(fn) {       
   var i = this.length;

   while(i--) {
       fn.call(this[i], i, this[i])
   }
};

การใช้งานเช่น:

$('#product-panel > div').reverse(function(i, e) {
    alert(i);
    alert(e);
});

ผมชอบความคิดนี้ / รหัสเกินไป แต่ก็ไม่ได้กลับวัตถุ chainable (นั่นเป็นสิ่งที่ตรงกันข้าม) เช่นสูงได้รับการโหวตคำตอบ :) ยังคงแน่นอนวิธีที่ดีสำหรับวิธีการของมันติดตั้ง
เอียน

คุณพูดถูก ไม่สามารถโยงได้ดังนั้นจึงไม่ใช่ปลั๊กอินที่ถูกต้อง มีการปรับปรุงรหัสเล็กน้อยแม้ว่าการย้ายตัวลดลงสู่สภาพ
James Westgate

8

หากคุณไม่ต้องการบันทึกวิธีลงใน jQuery.fn คุณสามารถใช้ได้

[].reverse.call($('li'));

นี่คือสิ่งที่ฉันกำลังมองหา
Alexander Dixon

5

จำเป็นต้องย้อนกลับบน $. แต่ละครั้งดังนั้นฉันจึงใช้ความคิด Vinay:

//jQuery.each(collection, callback) =>
$.each($(collection).get().reverse(), callback func() {});

ทำงานได้ดีขอบคุณ


สิ่งนี้ไม่ถูกต้อง $.each(collection.reverse(), ...)เพียงแค่นี้ควรจะเป็น
Sophie Alpert

@Ben Alpert - ความคิดเห็นของคุณมีข้อบกพร่องเนื่องจากการรวบรวมไม่ใช่อาร์เรย์ที่แท้จริง
vsync

4

คุณไม่สามารถทำซ้ำย้อนหลังด้วย jQuery แต่ละฟังก์ชัน แต่คุณยังสามารถใช้ประโยชน์จากไวยากรณ์ jQuery

ลองทำสิ่งต่อไปนี้:

//get an array of the matching DOM elements   
var liItems = $("ul#myUL li").get();

//iterate through this array in reverse order    
for(var i = liItems.length - 1; i >= 0; --i)
{
  //do Something
}

2

ผมพบว่าArray.prototype.reverseไม่ประสบความสำเร็จกับวัตถุดังนั้นฉันทำฟังก์ชัน jQuery jQuery.eachBack()ใหม่เพื่อใช้เป็นทางเลือก: มันวนซ้ำตามปกติjQuery.each()และเก็บแต่ละคีย์ไว้ในอาร์เรย์ จากนั้นจะย้อนกลับอาร์เรย์นั้นและดำเนินการโทรกลับบนอาร์เรย์ / วัตถุดั้งเดิมตามลำดับของปุ่มที่กลับด้าน

jQuery.eachBack=function (obj, callback) {
    var revKeys=[]; $.each(obj,function(rind,rval){revKeys.push(rind);}); 
    revKeys.reverse();
    $.each(revKeys,function (kind,i){
        if(callback.call(obj[i], i, obj[i]) === false) {    return false;}
    });
    return obj;
}   
jQuery.fn.eachBack=function (callback,args) {
    return jQuery.eachBack(this, callback, args);
}


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.