2010-10-19 19 views
5

Tôi có một cấu trúc menu gnarly có thể được khái quát như sau:khác biệt trong kết quả trả về giữa .has() và: có()

<ul id="navigation"> 
    <li> 
     A 
     <ul> 
      <li> 
       B 
       <ul> 
        <li>C</li> 
       </ul> 
      </li> 
      <li> 
       D 
       <ul> 
        <li> 
         E 
         <ul> 
          <li>F</li> 
         </ul> 
        </li> 
       </ul> 
      </li> 
     </ul> 
    </li> 
</ul> 

Tiểu mục được ẩn cho đến khi di chuột. Tôi muốn chỉ ra rằng B, D, và E có tiểu mục bằng cách tạo kiểu cho chúng vì vậy tôi sử dụng bộ chọn:

$('#navigation > li li:has(ul)') 

Mà chỉ trở lại B và D. Thay đổi nó để:

$('#navigation > li li').has('ul') 

trở tất cả các mục chính xác nhưng tôi nhầm lẫn là tại sao.

EDIT

:has() không xuất hiện để bị ảnh hưởng (hoàn toàn) bằng cách làm tổ như

$('#navigation ul > li:has(ul)') 

trả về kết quả tương tự như .has() trên.

+0

Dường như với tôi rằng kết quả sẽ giống nhau. Tôi không biết tại sao chúng khác nhau. Có lẽ Sizzle từ bỏ tìm kiếm trong các yếu tố lồng nhau khi một trận đấu được tìm thấy. Nếu vậy, điều này dường như bỏ qua khả năng của các yếu tố lồng nhau giống hệt nhau (như bạn có trong ví dụ của bạn). – user113716

Trả lời

7

Từ các tài liệu jQuery API:

:has chọn yếu tố mà chứa ít nhất một yếu tố mà phù hợp với selector cụ thể.

.has() giảm tập hợp các yếu tố phù hợp với số phù hợp với bộ chọn hoặc phần tử DOM.

Có một câu hỏi có liên quan ở đây: jQuery: subtle difference between .has() and :has(), dường như chỉ ra sự khác biệt trong hai điều có thể là gì.

Tuy nhiên, có vẻ như :has không nhìn trong một kết quả phù hợp theo kiểu lồng nhau trong khi .has() thực hiện bởi vì nó trả về một tập con của các đối sánh dưới dạng đối tượng jQuery có thể khớp với tất cả con cháu. Bộ chọn jQuery.

+3

Đó là những mô tả được sao chép từ các tài liệu [tại đây] (http://api.jquery.com/has-selector/) và [tại đây] (http://api.jquery.com/has/). Làm thế nào để nó làm cho chúng khác nhau? Dường như với tôi rằng họ nên trả lại kết quả tương tự. – user113716

+1

Liên kết bạn đăng cụ thể cho một vấn đề mà bộ chọn bắt đầu bằng '>'. – user113716

+1

Tôi phải đồng ý với @patrick - điều này hoàn toàn không trả lời được câu hỏi, mô tả ': has()' có nghĩa là * nên * tìm phần tử thứ ba, 'E'. Ngoài ra, bạn nên thích những mô tả này đến từ đâu. –

0

:has() selector chỉ chọn những phần tử có phần tử giảm dần được so khớp với bộ chọn đã cho. Bên trong, :has is defined như (Sizzle là jQuery mặc định thư viện selector):

function(elem, i, match){ 
    return !!Sizzle(match[3], elem).length; 
} 

này gần như tương đương với thử nghiệm jQuery("selector", elem).length hoặc jQuery(elem).find("selector").length cho mỗi phần tử được lựa chọn để lọc những người không có con cháu như vậy.

Ngược lại, has method có thể chọn bộ chọn hoặc phần tử DOM và chỉ trả lại những phần tử không chứa bất kỳ phần tử nào đã cho. Bởi vì trong nội bộ, các has method is defined như:

function(target) { 
    var targets = jQuery(target); 
    return this.filter(function() { 
     for (var i = 0, l = targets.length; i < l; i++) { 
      if (jQuery.contains(this, targets[i])) { 
       return true; 
      } 
     } 
    }); 
} 

Vì vậy, nó sử dụng contains method để kiểm tra xem các yếu tố nhất định được chứa để lọc các yếu tố lựa chọn. Lưu ý rằng nó chỉ đủ một trong các phần tử đã cho.

+1

Điều này không giải thích được hành vi, đây là lỗi trong Sizzle vì nó * nên * trả về các phần tử này, vấn đề là mảng các phần chọn được xuất hiện không chính xác trong kịch bản này. Ví dụ: '$ ('# navigation li li: has (ul)')' sẽ cho 3 phần tử. –

Các vấn đề liên quan