Nhận các phần tử theo thuộc tính khi không có querySelectorAll nếu không sử dụng các thư viện?


123
<p data-foo="bar">

Làm thế nào bạn có thể làm tương đương với

document.querySelectorAll('[data-foo]')

nơi querySelectorAllkhông có sẵn ?

Tôi cần một giải pháp gốc hoạt động ít nhất trong IE7. Tôi không quan tâm đến IE6.


kiểm tra thư viện bộ chọn javascript sizzle.js
epoch

1
Tuyệt vời, lựa chọn duy nhất tôi cần làm là thuộc tính dữ liệu, vì vậy tôi đã cố gắng tìm ra cách đơn giản nhất để vá lỗi đó mà không cần kéo toàn bộ công cụ chọn như Sizzle. Nhưng điểm tốt để xem trong nguồn. BTW một công cụ chọn tuyệt vời khác là github.com/ded/qwery
ryanve 29/02/12

@ryanve, cảm ơn tôi sẽ xem xét :)
epoch

Các giải pháp làm việc mà tôi sử dụng là trong github.com/ryanve/dope/blob/master/dope.js trong phương pháp gọi là 'queryAttr'
ryanve

7
Lol, câu hỏi của bạn là câu trả lời của tôi. Vì vậy, điều này đi kèm với một câu hỏi khác. Trong tình huống nào mà querySelectorAllkhông có sẵn? note - I don't care all IE
vzhen,

Câu trả lời:


136

Bạn có thể viết một hàm chạy getElementsByTagName ('*') và chỉ trả về những phần tử có thuộc tính "data-foo":

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++)
  {
    if (allElements[i].getAttribute(attribute) !== null)
    {
      // Element exists with attribute. Add to array.
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

Sau đó,

getAllElementsWithAttribute('data-foo');

8
Sử dụng != nulllà cách lý tưởng (tốt hơn so với nhận xét của tôi ở trên) vì trong IE cũ nó có thể cho getAttribute để trả về một giá trị mà typeof'number'
ryanve

1
Tại sao sử dụng document.getElementsByTagName('*')thay vì document.all?
pedrozath

1
Tại sao không sử dụng hasAttributehơn là getAttribute() !== null, vì bạn chỉ muốn kiểm tra sự tồn tại chứ không phải giá trị của nó?
rvighne

61

Sử dụng

//find first element with "someAttr" attribute
document.querySelector('[someAttr]')

hoặc là

//find all elements with "someAttr" attribute
document.querySelectorAll('[someAttr]') 

để tìm các phần tử theo thuộc tính. Nó hiện được hỗ trợ trong tất cả các trình duyệt có liên quan (ngay cả IE8): http://caniuse.com/#search=queryselector


2
Làm thế nào mà điều này lại có rất nhiều phiếu tán thành khi câu hỏi yêu cầu rõ ràng: "Tôi cần một giải pháp gốc hoạt động ít nhất trong IE7 ". Thứ hai, liên kết đó nói rằng hỗ trợ bắt đầu trong IE11 mặc dù nó thực sự bắt đầu từ IE8 - có thể điều này nên được hoán đổi thành developer.mozilla.org/en-US/docs/Web/API/Element/… để nó thực sự hỗ trợ câu trả lời. ..?
Zze

7
Lý do cho tất cả các phiếu ủng hộ và lý do tôi đưa ra câu trả lời, là câu hỏi SO này thực sự cũ, vì vậy khi bạn tìm kiếm cách tìm các phần tử DOM, bạn thấy câu hỏi này rất cao trong kết quả tìm kiếm và vì đó là những gì mọi người đang tìm kiếm họ ủng hộ. Tính hữu ích> độ chính xác lịch sử. Thứ hai liên kết vẫn hoạt động tốt, chỉ là caniuse.com đã ẩn các trình duyệt cũ, nếu bạn chuyển sang "Tương đối sử dụng" bạn sẽ vẫn thấy các trình duyệt cũ.
Pylinux 13:17

Hoạt động hoàn hảo. Nhanh chóng và đơn giản
Dawson B

Bây giờ là năm 2020. Đây sẽ là câu trả lời được chấp nhận ngay bây giờ.
NearHuscarl

44

Tôi đã chơi một chút và kết thúc với giải pháp thô thiển này:

function getElementsByAttribute(attribute, context) {
  var nodeList = (context || document).getElementsByTagName('*');
  var nodeArray = [];
  var iterator = 0;
  var node = null;

  while (node = nodeList[iterator++]) {
    if (node.hasAttribute(attribute)) nodeArray.push(node);
  }

  return nodeArray;
}

Cách sử dụng khá đơn giản và hoạt động ngay cả trong IE8:

getElementsByAttribute('data-foo');
// or with parentNode
getElementsByAttribute('data-foo', document);

http://fiddle.jshell.net/9xaxf6jr/

Nhưng tôi khuyên bạn nên sử dụng querySelector/ Allcho điều này (và để hỗ trợ các trình duyệt cũ hơn, hãy sử dụng polyfill ):

document.querySelectorAll('[data-foo]');

Vâng, +1 cho querySelectorAll. Một thử nghiệm jsperf nhanh jsperf.com/custom-vs-selectorall-attributes cho thấy nó nhanh hơn nhiều so với câu trả lời được chấp nhận ... tiếc là nó không phải là IE 7 tương thích :(
Sebastien Daniel

11

Hãy thử nó hoạt động

document.querySelector ('[thuộc tính = "giá trị"]')

thí dụ :

document.querySelector('[role="button"]')

5

Điều đó cũng hoạt động:

document.querySelector([attribute="value"]);

Vì thế:

document.querySelector([data-foo="bar"]);

2
Điều này thiếu các dấu ngoặc kép trong querySelector thực tế. Nên là: document.querySelector('[data-foo="bar"]');
Brettins,

1

Hãy thử điều này - Tôi đã thay đổi một chút các câu trả lời ở trên:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

Sau đó,

getAttributes('data-foo');

3
Bạn đã thay đổi điều gì và tại sao?
Artjom B.

1

Một chút sửa đổi trong câu trả lời của @kevinfahy , để cho phép nhận thuộc tính theo giá trị nếu cần:

function getElementsByAttributeValue(attribute, value){
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].getAttribute(attribute) !== null) {
      if (!value || allElements[i].getAttribute(attribute) == value)
        matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

0

Không sử dụng trong Trình duyệt

Trong trình duyệt, sử dụng document.querySelect('[attribute-name]').

Nhưng nếu bạn đang thử nghiệm đơn vị và dom bị chế nhạo của bạn có triển khai querySelector không ổn định, điều này sẽ thực hiện được mẹo.

Đây là câu trả lời của @ kevinfahy.

Vì vậy, nó sẽ chỉ hoạt động với một trình chuyển tiếp ES6. Ngoài ra, tôi không chắc nó sẽ hoạt động như thế nào với nhiều yếu tố.

function getElementsWithAttribute(attribute) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) !== null);
}

Và đây là một biến thể sẽ nhận được một thuộc tính với một giá trị cụ thể

function getElementsWithAttributeValue(attribute, value) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) === value);
}
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.