Làm thế nào để có được phần tử con theo tên lớp?


131

Tôi đang cố gắng để có được khoảng con có một lớp = 4. Đây là một yếu tố ví dụ:

<div id="test">
 <span class="one"></span>
 <span class="two"></span>
 <span class="three"></span>
 <span class="four"></span>
</div>

Các công cụ tôi có sẵn là JS và YUI2. Tôi có thể làm một cái gì đó như thế này:

doc = document.getElementById('test');
notes = doc.getElementsByClassName('four');

//or

doc = YAHOO.util.Dom.get('#test');
notes = doc.getElementsByClassName('four');

Chúng không hoạt động trong IE. Tôi gặp một lỗi mà đối tượng (doc) không hỗ trợ phương thức hoặc thuộc tính này (getElementsByClassName). Tôi đã thử một vài ví dụ về việc triển khai trình duyệt chéo của getElementsByClassName nhưng tôi không thể làm cho chúng hoạt động và vẫn gặp lỗi đó.

Tôi nghĩ cái tôi cần là một trình duyệt chéo getElementsByClassName hoặc tôi cần sử dụng doc.getElementsByTagName ('span') và lặp lại cho đến khi tôi tìm thấy lớp 4. Mặc dù vậy tôi không chắc chắn làm thế nào để làm điều đó.



1
Hài hước lắm, mạnh mẽ hơn querySelectorAllđược IE 8+ getElementsByClassNamehỗ trợ trong khi chỉ được IE 9+ hỗ trợ. Nếu bạn có thể bỏ IE 7, bạn có thể sử dụng an toàn querySelectorAll('.4'). Nhân tiện, 4là một tên lớp không hợp lệ.
Prinzhorn

@paritybit câu hỏi đó không hoạt động vì nó vẫn sử dụng getElementsByClassName và phiên bản IE cũ hơn dường như không hỗ trợ điều đó. chỉnh sửa: Tôi xin lỗi nó sử dụng tên thẻ. Điều này có thể làm việc.
spyderman4g63

@Prinzhorn Tôi không có tiện ích chọn YUI2 trong sản phẩm này vì một số lý do.
spyderman4g63

@ spyderman4g63 Tôi không nói gì về YUI2 cụ thể. document.querySelectorAlllà DOM và không liên quan gì đến YUI
Prinzhorn

Câu trả lời:


85

Sử dụng doc.childNodesđể lặp qua từng cái span, và sau đó lọc cái có giá trị classNamebằng 4:

var doc = document.getElementById("test");
var notes = null;
for (var i = 0; i < doc.childNodes.length; i++) {
    if (doc.childNodes[i].className == "4") {
      notes = doc.childNodes[i];
      break;
    }        
}

Hay nói, là một tài tài của, qua, qua, qua một tài khác, qua giữ, qua một tài khác


1
Vấn đề là getElementsByClassName không hoạt động trong IE8.
spyderman4g63

7
Mã này không hoạt động nếu phần tử có nhiều hơn một lớp. Ví dụ: nếu bạn đang tìm kiếm các phần tử với lớp "một" và các phần tử của bạn có lớp "một hai ba", hàm này sẽ không tìm thấy chúng.
Fran Verona

3
@FranVerona Chỉ cần tò mò, một "indexOf ('className')> -1" đơn giản sẽ giải quyết vấn đề nhiều lớp?
James Poulose 4/1/2015

2
@JamesPoulose, nó sẽ không . Xem xét có một phần tử được đặt thành hai lớp: nhỏ và lớn hơn. thatEuity.groupName sẽ trả về một Chuỗi bằng "nhỏ hơn". Nếu bạn đang tìm kiếm một lớp được gọi là myEuity. ClassName.indexOf ("lớn") sẽ tạo ra một cái gì đó không bằng âm 1 mặc dù đó không thực sự là một phần của lớp. Nếu bạn có 100% quyền kiểm soát tên lớp của mình, cách khắc phục như vậy sẽ có hiệu quả, điều đó sẽ không được đảm bảo, đặc biệt là khi mã viết của bạn sẽ tương tác với mã mà bạn không có toàn quyền kiểm soát.
deadboy

Bạn nên sử dụng một kết hợp regex classNamegiống như vậy: if(doc.childNode[i].className.match("\s*" + search_class + "\s*")trong đó biến search_classlà tên lớp mà bạn đang tìm kiếm.
WebWanderer 18/03/2016

130

Sử dụng querySelector và querySelector ALL

var testContainer = document.querySelector('#test');
var fourChildNode = testContainer.querySelector('.four');

IE9 trở lên

;)


Cảm ơn giải pháp thông minh của bạn!
Tai JinYuan

1
Điều này kiểm tra cho tất cả con cháu, không chỉ trẻ em.
SUM1

47

Câu trả lời được chấp nhận chỉ kiểm tra trẻ em ngay lập tức. Thường thì chúng ta đang tìm kiếm bất kỳ hậu duệ nào có tên lớp đó.

Ngoài ra, đôi khi chúng tôi muốn bất kỳ đứa trẻ nào chứa className.

Ví dụ: <div class="img square"></div>nên khớp với tìm kiếm trên className "img", mặc dù tên chính xác của className không phải là "img".

Đây là một giải pháp cho cả hai vấn đề này:

Tìm ví dụ đầu tiên của một phần tử con cháu với lớp className

   function findFirstChildByClass(element, className) {
        var foundElement = null, found;
        function recurse(element, className, found) {
            for (var i = 0; i < element.childNodes.length && !found; i++) {
                var el = element.childNodes[i];
                var classes = el.className != undefined? el.className.split(" ") : [];
                for (var j = 0, jl = classes.length; j < jl; j++) {
                    if (classes[j] == className) {
                        found = true;
                        foundElement = element.childNodes[i];
                        break;
                    }
                }
                if(found)
                    break;
                recurse(element.childNodes[i], className, found);
            }
        }
        recurse(element, className, false);
        return foundElement;
    }

7
Không. Tôi không muốn tất cả con cháu, chỉ là đứa trẻ như câu hỏi.
Paul Draper

14
Whelp. Nhận xét của bạn là cần thiết. Vui mừng tôi đã giúp 13 người khác (như tôi) thường tìm kiếm các câu trả lời tương tự để giải quyết vấn đề tương tự nhưng có lẽ phức tạp hơn hoặc phức tạp hơn của họ.
Augie Gardner

5
tnx, tôi nghĩ rằng câu trả lời này phù hợp với nhiều trường hợp sử dụng hơn
Boban Stojanovski

Đối với hồ sơ, tôi đã có cả hai trường hợp sử dụng, con cháu thường xuyên hơn một chút, nhưng tôi đến đây cho trường hợp sử dụng trẻ em.
SUM1

14

Sử dụng phần tử.querySelector (). Giả sử: 'myEuity' là phần tử cha bạn đã có. 'sonClassName' là lớp của đứa trẻ bạn đang tìm kiếm.

let child = myElement.querySelector('.sonClassName');

Để biết thêm thông tin, hãy truy cập: https://developer.mozilla.org/en-US/docs/Web/API/Euity/querySelector


Vì một số lý do, tôi đã phải sử dụng let child = myElement.querySelector('sonClassName');trong trường hợp của mình
malat

Nhưng bạn phải thêm dấu chấm bên cạnh truy vấn tên lớpSelector ('. SonClassName'), nếu không nó sẽ xử lý nó vì sonClassName là tên thẻ không phải là tên lớp
Hamza Dahmoun

10

Bạn có thể thử:

notes = doc.querySelectorAll('.4');

hoặc là

notes = doc.getElementsByTagName('*');
for (var i = 0; i < notes.length; i++) { 
    if (notes[i].getAttribute('class') == '4') {
    }
}

1
Tôi đã tự hỏi nếu cuối cùng các trình duyệt có chức năng này mà không yêu cầu một cái gì đó như jQuery, vui mừng khi thấy nó. Nếu bất kỳ ai cũng tò mò, có vẻ như nó được hỗ trợ trong hầu hết các trình duyệt hiện đại: developer.mozilla.org/en-US/docs/Web/API/Document/
Kẻ

8

Đối với tôi có vẻ như bạn muốn nhịp thứ tư. Nếu vậy, bạn chỉ có thể làm điều này:

document.getElementById("test").childNodes[3]

hoặc là

document.getElementById("test").getElementsByTagName("span")[3]

Cái cuối cùng này đảm bảo rằng không có bất kỳ nút ẩn nào có thể làm hỏng nó.


1
Cảm ơn, nhưng có một số lượng các yếu tố con.
spyderman4g63

1
Đối với tôi có vẻ như câu hỏi là luôn luôn có được đứa con thứ tư, do đó dẫn đến câu trả lời của tôi. Tất nhiên tôi đồng ý rằng một hàm để lấy bất kỳ loại phần tử nào ở bất kỳ chỉ số nào trong một phần tử khác sẽ tốt hơn, nhưng tôi không diễn giải câu hỏi như thế ... đọc lại câu hỏi tôi thấy rằng tôi hoàn toàn hiểu sai: - )
Christian Jørgensen

TagNameđó là nó! Quá đơn giản.
Jacksonkr

Tôi sử dụng kỹ thuật này thường xuyên để có được phần tử đầu tiên, ví dụ document.getEuityById ("test"). ChildNodes [0]
Louise Eggleton

@LouiseEggleton có .firstChild.firstChildElementmặc dù
YakovL

4

Nhưng hãy lưu ý rằng các trình duyệt cũ không hỗ trợ getElementsByClassName.

Sau đó, bạn có thể làm

function getElementsByClassName(c,el){
    if(typeof el=='string'){el=document.getElementById(el);}
    if(!el){el=document;}
    if(el.getElementsByClassName){return el.getElementsByClassName(c);}
    var arr=[],
        allEls=el.getElementsByTagName('*');
    for(var i=0;i<allEls.length;i++){
        if(allEls[i].className.split(' ').indexOf(c)>-1){arr.push(allEls[i])}
    }
    return arr;
}
getElementsByClassName('4','test')[0];

Có vẻ như nó hoạt động, nhưng lưu ý rằng một lớp HTML

  • Phải bắt đầu bằng một chữ cái: AZ hoặc az
  • Có thể được theo sau bởi các chữ cái (A-Za-z), chữ số (0-9), dấu gạch nối ("-") và dấu gạch dưới ("_")

3

Sử dụng tên của id với getElementById, không có #dấu trước nó. Sau đó, bạn có thể lấy các spannút con bằng cách sử dụng getElementsByTagNamevà lặp qua chúng để tìm nút có lớp đúng:

var doc = document.getElementById('test');

var c = doc.getElementsByTagName('span');

var e = null;
for (var i = 0; i < c.length; i++) {
    if (c[i].className == '4') {
        e = c[i];
        break;
    }
}

if (e != null) {
    alert(e.innerHTML);
}

Bản trình diễn: http://jsfiddle.net/Guffa/xB62U/


Xin lỗi, đó là một lỗi đánh máy. Tôi có thể chọn div container, nhưng không thể chọn các phần tử con theo tên thẻ vì hàm đó không hoạt động trong eg8.
spyderman4g63

@ spyderman4g63: getElementsByTagNamePhương thức này hoạt động trong IE 8. Nó được hỗ trợ cho đến tận IE 5.5. developer.mozilla.org/en-US/docs/DOM/ Từ
Guffa

3

Theo tôi, mỗi khi bạn có thể, bạn nên sử dụng Array và các phương thức của nó. Chúng nhanh hơn nhiều, sau đó lặp lại toàn bộ DOM / trình bao bọc hoặc đẩy công cụ vào mảng trống. Phần lớn các giải pháp được trình bày ở đây bạn có thể gọi Naive như được mô tả ở đây (bài viết tuyệt vời btw):

https://medium.com/@chuckdries/traversing-the-dom-with-filter-map-and-arrow-fifts-1417d326d2bc

Giải pháp của tôi : (xem trước trực tiếp trên Codepen: https://codepen.io/Nikolaus91/pen/wEGEYe )

const wrapper = document.getElementById('test') // take a wrapper by ID -> fastest
const itemsArray = Array.from(wrapper.children) // make Array from his children

const pickOne = itemsArray.map(item => { // loop over his children using .map() --> see MDN for more
   if(item.classList.contains('four')) // we place a test where we determine our choice
     item.classList.add('the-chosen-one') // your code here
})

1

Cách tôi sẽ làm điều này bằng cách sử dụng jquery là một cái gì đó như thế này ..

var Targetchild = $ ("# test"). children (). find ("span.four");


14
câu hỏi là về javascript chứ không phải jQuery
Jya 31/12/14

1

Đây là một giải pháp đệ quy tương đối đơn giản. Tôi nghĩ rằng một tìm kiếm đầu tiên là thích hợp ở đây. Điều này sẽ trả về phần tử đầu tiên phù hợp với lớp được tìm thấy.

function getDescendantWithClass(element, clName) {
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (children[i].className &&
            children[i].className.split(' ').indexOf(clName) >= 0) {
            return children[i];
         }
     }
     for (var i = 0; i < children.length; i++) {
         var match = getDescendantWithClass(children[i], clName);
         if (match !== null) {
             return match;
         }
     }
     return null;
}

1

Bạn có thể tìm nạp lớp cha bằng cách thêm dòng bên dưới. Nếu bạn có một id, nó sẽ dễ dàng hơn với getElementById. Tuy nhiên,

var parentNode = document.getElementsByClassName("progress__container")[0];

Sau đó, bạn có thể sử dụng querySelectorAlltrên cha mẹ <div>để tìm nạp tất cả các kết quả khớp divvới lớp.progress__marker

var progressNodes = progressContainer.querySelectorAll('.progress__marker');

querySelectorAllsẽ tìm nạp mọi thứ divvới lớpprogress__marker


1

Giải pháp hiện đại

const context = document.getElementById('context');
const selected = context.querySelectorAll(':scope > div');

tài liệu


0

Cập nhật tháng 6 năm 2018 lên ES6

    const doc = document.getElementById('test');
    let notes = null;
    for (const value of doc) {
        if (value.className === '4') {
            notes = value;
            break;
        }    
    }

-2

Hừm. Ví dụ này hoạt động trong IE8, nhưng có thể nó không hoạt động trong trường hợp bạn áp dụng nó cho một đối tượng. Trong trường hợp của tôi, đặt doc là một đối tượng dom yui và sau đó sử dụng doc.getElementsByClassName. Đó là khi nó thất bại. chỉnh sửa: hoặc có thể tôi không hiểu làm thế nào đối tượng đó hoạt động và nó chỉ là một đối tượng dom bình thường?
spyderman4g63

@ spyderman4g63 phiên bản YUI getElementsByClassNamelà một phương pháp YAHOO.util.Dom. Trong trường hợp của bạn, cuộc gọi sẽ trông giống như YAHOO.util.Dom.getElementsByClassName('four', 'span', 'test'). Bạn có lẽ nên đọc các tài liệu để hiểu rõ hơn về những gì cuộc gọi đó đang làm. Các phiên bản ngắn là bây giờ nó sẽ tìm kiếm spancác yếu tố với các lớp fourbên dưới phần tử DOM với testnhư nó id.
Hank Gay

@ spyderman4g63 Có, kết quả của getcuộc gọi chỉ là một phần tử DOM. YUI không thực hiện kiểu bán toàn bộ 'bao bọc mọi thứ theo cách tiếp cận đối tượng cụ thể theo khung' giống như jQuery, cũng như không vá các đối tượng gốc như Prototype (đã làm gì? Tôi đã nhầm lẫn với w / Protoype mãi mãi). Về mặt này, YUI giống như Dojo hơn.
Hank Gay

-3

Đây là cách tôi đã làm nó bằng cách sử dụng các bộ chọn YUI. Cảm ơn đề nghị của Hank Gay.

notes = YAHOO.util.Dom.getElementsByClassName('four','span','test');

trong đó bốn = classname, span = loại phần tử / tên thẻ và test = id cha.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.