Chọn tất cả các thành phần có thuộc tính data data- mà không cần sử dụng jQuery


233

Chỉ sử dụng JavaScript, cách hiệu quả nhất để chọn tất cả các thành phần DOM có data-thuộc tính nhất định (giả sử data-foo). Các yếu tố có thể là các yếu tố thẻ khác nhau.

<p data-foo="0"></p><br/><h6 data-foo="1"></h6>

Hãy nhớ rằng document.querySelectorAllkhông hoạt động trên IE7. Bạn sẽ phải tạo một tập lệnh dự phòng sẽ đi theo cây DOM và kiểm tra thuộc tính trong mỗi thẻ (thực sự tôi không biết tốc độ của querySelectorAllnó là bao nhiêu và sẽ đi kiểm tra thẻ thủ công).
tereško

Lý do của bạn không sử dụng jQuery là gì? Nó khá là không thể thay thế trong những tình huống như thế này ...
James Hay

@hay không hề, bạn thậm chí có thể chọn các yếu tố này trong css thuần túy.
Knu

1
@JamesHay vì không phải mọi môi trường, công ty, trang web, tiêu chuẩn mã hóa, những gì có bạn, đều cho phép sử dụng jQuery. jQuery không thể thay thế.
Carnix

1
Tôi vẫn không thấy bất kỳ câu trả lời thực sự hoạt động trên khác nhau data- các yếu tố, ví dụ: data-foo=0data-bar=1 data-app="js" data-date="20181231"
Alex

Câu trả lời:



244
document.querySelectorAll("[data-foo]")

sẽ giúp bạn có được tất cả các yếu tố với thuộc tính đó.

document.querySelectorAll("[data-foo='1']")

sẽ chỉ giúp bạn có được giá trị 1.


Làm thế nào bạn có thể thiết lập các giá trị cho các yếu tố bạn nhận được?
Steven Aguilar

@StevenAguilar .querySelectorAll()trả lại a NodeList. Như đã lưu ý trong tài liệu đó, bạn có thể lặp lại bộ sưu tập bằng cách sử dụng .forEach(). Lưu ý rằng đây là giải pháp không dành cho IE: developer.mozilla.org/en-US/docs/Web/API/ mẹo . Nếu bạn cần hỗ trợ IE, bạn sẽ phải lặp qua NodeList bằng một forvòng lặp thông thường .
Joseph Marikle

13

Hãy thử nó → tại đây

    <!DOCTYPE html>
    <html>
        <head></head>
        <body>
            <p data-foo="0"></p>
            <h6 data-foo="1"></h6>
            <script>
                var a = document.querySelectorAll('[data-foo]');

                for (var i in a) if (a.hasOwnProperty(i)) {
                    alert(a[i].getAttribute('data-foo'));
                }
            </script>
        </body>
    </html>

Sử dụng hasOwnProperty là câu trả lời tốt nhất cho tôi cho đến năm 2016, điều này rất nhanh liên quan đến các cách lặp khác MDN hasOwnProperty
NVRM

NodeList từ querySelectorAll () có thể lặp lại (mặc dù không phải là một mảng). Vòng lặp với for insẽ lặp lại theo các thuộc tính chiều dài và vật phẩm. Thay vào đó, sử dụng for ofđể lặp lại các thuộc tính được thiết kế để lặp đi lặp lại
Solvitieg 21/03/19

1

Đây là một giải pháp thú vị: nó sử dụng công cụ CSS của trình duyệt để thêm thuộc tính giả cho các thành phần khớp với bộ chọn và sau đó đánh giá kiểu tính toán để tìm các phần tử phù hợp:

Nó tự động tạo ra một quy tắc kiểu [...] Sau đó, nó sẽ quét toàn bộ tài liệu (sử dụng tài liệu rất cụ thể và rất cụ thể của IE nhưng rất nhanh) và có được kiểu tính toán cho từng thành phần. Sau đó, chúng tôi tìm kiếm thuộc tính foo trên đối tượng kết quả và kiểm tra xem nó có đánh giá là thanh bar hay không. Đối với mỗi phần tử phù hợp, chúng tôi thêm vào một mảng.


1
Phải, tôi loại bỏ gợi ý về các trình duyệt cũ.
Heinrich Ulbricht

Cảm ơn rất nhiều thưa ngài;) Tôi phải thú nhận rằng tôi đã bỏ qua 5.
Heinrich Ulbricht

yeah dễ bỏ lỡ thẻ. bởi vì đó là html5 nên tất cả chúng tôi đều đề xuất document.querySelector ALL (và thuộc tính data- * cũng cụ thể là html5).
Shawndumas

-1
var matches = new Array();

var allDom = document.getElementsByTagName("*");
for(var i =0; i < allDom.length; i++){
    var d = allDom[i];
    if(d["data-foo"] !== undefined) {
         matches.push(d);
    }
}

Không chắc ai đã cho tôi bằng -1, nhưng đây là bằng chứng.

http://jsfiddle.net/D798K/2/


3
bạn hầu như "đúng" chỉ là không đúng. Tôi khá chắc chắn rằng ai đó đã cho bạn -1 vì bạn đang làm rất nhiều việc để có được các yếu tố, và sau đó đặt bộ sưu tập vào một mảng. Tôi đã không cho -1 chỉ không thích khi không có lời giải thích cho một.
Loktar

1
đắt tiền (tất cả các yếu tố trên trang), cũng sử dụng ký hiệu mảng (nghĩa là []), và trên đầu trang, nó không hoạt động. xem cho chính mình -> jsbin.com/ipisul/edit#javascript,html
Shawndumas

2
Mặc dù OP đang sử dụng HTML 5, nhưng getElementsByTagNamevới *bộ chọn toàn cầu ( ) bị hỏng trong các bản dựng IE cũ hơn. Đây là nơi tìm kiếm DOM đệ quy hoàn thành công việc. Cũng không có thuộc tính "data-foo" trên ElementNode được ánh xạ từ data-foothuộc tính. Bạn đang tìm kiếm datasetđối tượng (ví dụ : node.dataset.foo.

@shawndumas - nó xuất hiện bất cứ thứ gì bạn đang có là PEBKAC. jsfiddle.net/D798K/2 . Nó hoạt động. Cuối cùng, tôi tự -1 cho câu trả lời này bằng mọi cách - Tôi đã bỏ lỡ những từ "hiệu quả nhất" trong câu hỏi của OP ...
Brian

@ Brian - hiện jsbin.com/ipisul việc một cho bạn? bởi vì jsfiddle của bạn không hoạt động trong (nơi làm việc được yêu cầu) của tôi tức là 9 ...
Shawndumas

-4

Mặc dù không đẹp như querySelectorAll(có nhiều vấn đề), đây là một chức năng rất linh hoạt, đệ quy DOM và sẽ hoạt động trong hầu hết các trình duyệt (cũ và mới). Miễn là trình duyệt hỗ trợ điều kiện của bạn (ví dụ: thuộc tính dữ liệu), bạn sẽ có thể truy xuất phần tử.

Đối với người tò mò: Đừng bận tâm kiểm tra điều này so với QSA trên jsPerf. Các trình duyệt như Opera 11 sẽ lưu trữ truy vấn và làm lệch kết quả.

Mã số:

function recurseDOM(start, whitelist)
{
    /*
    *    @start:        Node    -    Specifies point of entry for recursion
    *    @whitelist:    Object  -    Specifies permitted nodeTypes to collect
    */

    var i = 0, 
    startIsNode = !!start && !!start.nodeType, 
    startHasChildNodes = !!start.childNodes && !!start.childNodes.length,
    nodes, node, nodeHasChildNodes;
    if(startIsNode && startHasChildNodes)
    {       
        nodes = start.childNodes;
        for(i;i<nodes.length;i++)
        {
            node = nodes[i];
            nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length;
            if(!whitelist || whitelist[node.nodeType])
            {
                //condition here
                if(!!node.dataset && !!node.dataset.foo)
                {
                    //handle results here
                }
                if(nodeHasChildNodes)
                {
                    recurseDOM(node, whitelist);
                }
            }
            node = null;
            nodeHasChildNodes = null;
        }
    }
}

Sau đó, bạn có thể bắt đầu nó với những điều sau đây:

recurseDOM(document.body, {"1": 1}); cho tốc độ, hoặc chỉ recurseDOM(document.body);

Ví dụ với đặc điểm kỹ thuật của bạn: http://jsbin.com/unajot/1/edit

Ví dụ với thông số kỹ thuật khác nhau: http://jsbin.com/unajot/2/edit


23
Các vấn đề với vấn đề là querySelectorAllgì?
ShreevatsaR

9
Tôi cũng rất thích nghe về những vấn đề này.
Sean_A91

4
Bây giờ, chúng tôi sẽ không bao giờ biết litany đó là gì. Thêm một chương nữa cho Bí ẩn vĩnh cửu từ SO
brasofilo

hạ thấp điều này. Nó hoàn toàn bị mã hóa và không cần thiết với querySelectorAllapi
dman
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.