การใช้ 'เริ่มต้นด้วย' ตัวเลือกสำหรับชื่อคลาสแต่ละรายการ


158

หากฉันมีดังต่อไปนี้:

<div class="apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

ฉันสามารถใช้ตัวเลือกต่อไปนี้เพื่อค้นหา DIV สองตัวแรก:

$("div[class^='apple-']")

อย่างไรก็ตามถ้าฉันมีสิ่งนี้:

<div class="some-other-class apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

จะพบเฉพาะ DIV ตัวที่สองเนื่องจากคลาสของ div แรกถูกส่งคืนเป็นสตริง (ฉันคิดว่า) และไม่ได้เริ่มต้นด้วย 'apple-' แต่แทนที่จะเป็น 'some-'

วิธีหนึ่งที่ไม่ควรใช้เริ่มต้นด้วย แต่มี:

$("div[class*='apple-']")

ปัญหาที่เกิดขึ้นคือมันจะเลือก DIV ที่ 3 ในตัวอย่างของฉัน

คำถาม: ผ่าน jQuery วิธีที่เหมาะสมในการใช้ตัวเลือกเพรดิเคตกับชื่อคลาสแต่ละชื่อแทนที่จะใช้แอตทริบิวต์คลาสทั้งหมดเป็นสตริง มันเป็นแค่เรื่องของการคว้า CLASS แล้วแยกมันออกเป็นอาเรย์แล้ววนซ้ำแต่ละอันด้วย regex? หรือมีวิธีการแก้ปัญหา verbose ที่หรูหรา / น้อยกว่ามากขึ้น?

คำตอบ:


304

คลาสที่เริ่มต้นด้วย "apple-" บวกคลาสที่มี "apple-"

$("div[class^='apple-'],div[class*=' apple-']")

5
+1 แม้ว่าฉันจะเห็นด้วยกับข้อเสนอแนะของ @parrots ว่า "แอปเปิ้ล" ควรเป็นคลาสของตัวเองที่นี่เนื่องจากเห็นได้ชัดว่ามันซ้อนทับหลาย divs แต่เป็นเอนทิตี้ที่แตกต่างกัน แต่นี่จะแก้ปัญหาได้
jvenema

อืม ... ฉลาด! ฉันไม่ได้คิดถึงการใช้พื้นที่ในนั้น สามารถใช้โอเปอเรเตอร์บูลีนใน jquery selector ได้หรือไม่? ตามหลักการแล้วข้างต้นจะเป็น 'OR' เพื่อหลีกเลี่ยงกรณี (หายากและหลีกเลี่ยงได้) ซึ่งมีมากกว่าหนึ่งชั้นที่จ้องมองด้วย 'apple-'
DA

ไม่แน่ใจว่าผมเข้าใจ แต่ถ้าคุณเพียงต้องการที่จะใช้ตัวเลือกที่สองเมื่อคืนตัวเลือกแรกที่ศูนย์องค์ประกอบคุณสามารถทำอะไรเช่นนี้: var divs = $("div[class^='apple-']"); if(divs.length == 0) divs = $("div[class*=' apple-']");
จอช Stodola

ตอนนี้ฉันคิดถึงมันแล้วทางออกแรกของคุณก็ใช้ได้ดี DIV ที่มีคลาสเช่น "apple-brick apple-horse" จะยังคงถูกเลือกเพียงครั้งเดียวในวัตถุ jQuery
ดา

ใช้ * แทน div ถ้าคุณไม่ได้วิ่งชั้นเรียนสำหรับองค์ประกอบเฉพาะ :)
Hidayt เราะห์มาน

13

ฉันขอแนะนำให้สร้าง "แอปเปิ้ล" เป็นคลาสของตัวเอง คุณควรหลีกเลี่ยงการเริ่มต้นด้วย / สิ้นสุด - ด้วยถ้าทำได้เพราะความสามารถในการเลือกใช้div.appleจะเร็วขึ้นมาก นั่นเป็นทางออกที่หรูหรากว่า อย่ากลัวที่จะแยกสิ่งต่าง ๆ ออกเป็นชั้น ๆ ถ้ามันทำให้งานง่ายขึ้น / เร็วขึ้น


คุณคิดว่ามันจะเร็วขึ้นได้อย่างไร? มันยังคงต้องสแกน DOM ทั้งหมดและประเมินคุณลักษณะคลาส มันจะเร็วขึ้นเล็กน้อย (อย่างดีที่สุด) เพราะมันจะไม่ต้องซับสตริงแอตทริบิวต์ class เล็กน้อย
Josh Stodola

2
componenthouse.com/article-19 : ถ้าคุณดูในส่วนของการรับตามคลาสการใช้ไวยากรณ์จุดปกติมักจะเป็นบิตที่เร็วกว่าการใช้คลาสเป็นแอตทริบิวต์ เพิ่มการค้นหาสตริงย่อย (และงานเพิ่มเติมที่เขาจะต้องทำเพื่อแยกองค์ประกอบที่มีชื่อคลาสหลายชื่อ) และมันจะเพิ่มประสิทธิภาพการประหยัดที่เหมาะสม
แพร์รอทส์

1
ฉันเห็นด้วย. สิ่งที่จับได้คือเรายังคงสนับสนุน IE6 อย่างหนักและไม่รองรับตัวเลือกแบบผสมใน CSS: .class1.class2.class3 เช่นนี้เรากำลังใช้ชื่อคลาสที่ยาวกว่าโดยที่ 'พารามิเตอร์' ถูกแบ่งด้วยเครื่องหมายขีดกลาง
ดา

6

นี่คือคำนำหน้าด้วย

$("div[class^='apple-']")

นี่คือการเริ่มต้นด้วยดังนั้นคุณไม่จำเป็นต้องมีอักขระ '-' ในนั้น

$("div[class|='apple']")

คุณสามารถค้นหารูปแบบดีๆอื่น ๆ ของตัวเลือก jQuery ได้ที่นี่ https://api.jquery.com/category/selectors/


6

ในขณะที่คำตอบยอดนิยมที่นี่เป็นวิธีแก้ปัญหาสำหรับกรณีเฉพาะของผู้ถามหากคุณกำลังมองหาวิธีการแก้ปัญหาโดยใช้ 'เริ่มต้นด้วย' กับชื่อคลาสแต่ละรายการ:

คุณสามารถใช้ตัวเลือก jQuery ที่กำหนดเองนี้ซึ่งฉันเรียกว่า:acp()"คำนำหน้าชั้น A" รหัสอยู่ที่ด้านล่างของโพสต์นี้

var test = $('div:acp("starting_text")');

สิ่งนี้จะเลือก<div>องค์ประกอบใด ๆ และทั้งหมดที่มีชื่อคลาสอย่างน้อยหนึ่งชื่อขึ้นต้นด้วยสตริงที่กำหนด ("Starting_text" ในตัวอย่างนี้) โดยไม่คำนึงว่าคลาสนั้นจะอยู่ที่จุดเริ่มต้นหรือที่อื่นในสตริงแอตทริบิวต์คลาส

<div id="1" class="apple orange lemon" />
<div id="2" class="orange applelemon banana" />
<div id="3" class="orange lemon apple" />
<div id="4" class="lemon orangeapple" />
<div id="5" class="lemon orange" />

var startsWithapp = $('div:acp("app")');

สิ่งนี้จะคืนค่าองค์ประกอบ 1, 2 และ 3 แต่ไม่ใช่ 4 หรือ 5

นี่คือการประกาศสำหรับ:acpตัวเลือกที่กำหนดเองซึ่งคุณสามารถใส่ได้ทุกที่:

$(function(){
    $.expr[":"].acp = function(elem, index, m){
          var regString = '\\b' + m[3];
          var reg = new RegExp(regString, "g");
          return elem.className.match(reg);
    }
});

ฉันทำสิ่งนี้เพราะฉันทำ GreaseMonkey การแฮ็คเว็บไซต์ที่ฉันไม่มีการควบคุมแบ็คเอนด์ดังนั้นฉันมักจะต้องค้นหาองค์ประกอบที่มีชื่อคลาสที่มีคำต่อท้ายแบบไดนามิก มันมีประโยชน์มาก



2
<div class="apple-monkey"></div>
<div class="apple-horse"></div>
<div class="cow-apple-brick"></div>

ในกรณีนี้เป็นคำถามที่คำตอบ Josh Stodola เป็นคลาสที่ถูกต้องที่เริ่มต้นด้วย "apple-" บวกคลาสที่มี "apple-"

$("div[class^='apple-'],div[class*=' apple-']")

แต่ถ้าองค์ประกอบมีหลายคลาสเช่นนี้

<div class="some-class apple-monkey"></div>
<div class="some-class apple-horse"></div>
<div class="some-class cow-apple-brick"></div>

จากนั้นวิธีแก้ปัญหาของ Josh Stodola จะไม่ทำงาน
สำหรับสิ่งนี้ต้องทำบางสิ่งเช่นนี้

$('.some-parent-class div').filter(function () {
  return this.className.match(/\bapple-/);// this is for start with
  //return this.className.match(/apple-/g);// this is for contain selector
}).css("color","red");

อาจจะช่วยให้คนอื่นขอบคุณ


0

หากองค์ประกอบมีคลาสทวีคูณ "[class ^ = 'apple-']" ไม่สามารถใช้งานได้เช่น

<div class="fruits apple-monkey"></div>

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