Tìm kiếm phương thức find find (..) của jQuery bao gồm nút hiện tại


134

Phương thức truyền tải tìm kiếm jQuery (..) không bao gồm nút hiện tại - nó bắt đầu với các phần tử con của nút hiện tại. Cách tốt nhất để gọi một hoạt động tìm bao gồm nút hiện tại trong thuật toán phù hợp của nó là gì? Nhìn qua các tài liệu không có gì ngay lập tức nhảy ra khỏi tôi.

Câu trả lời:


153

Đối với jQuery 1.8 trở lên, bạn có thể sử dụng .addBack(). Phải mất một bộ chọn để bạn không cần phải lọc kết quả:

object.find('selector').addBack('selector')

Trước jQuery 1.8, bạn đã bị mắc kẹt .andSelf(), (hiện không dùng nữa và đã bị xóa) mà sau đó cần lọc:

object.find('selector').andSelf().filter('selector')

5
Tôi đã gói cái này dưới dạng plugin jquery.findIncludeSelf, đã đăng ký với Bower. Xem github.com/ronen/jquery.findIncludeSelf
ronen

18
@ronen Một tập tin bổ sung cho một cái gì đó có thể được thực hiện trong một dòng? Cảm ơn, nhưng không cảm ơn.

6
@ prc322 một tệp bổ sung không làm phiền tôi khi triển khai gói tất cả các javascript vào một tệp duy nhất. Nói chung, tôi thích sử dụng các phương thức thư viện (đã thử nghiệm) ngay cả đối với những điều đơn giản, thay vì làm lộn xộn mã của tôi với những thứ mà tôi thấy khó đọc hơn và điều đó đưa ra nhiều khả năng hơn cho các lỗi. Trong trường hợp này nói riêng, IMHO cần chỉ định 'selector'hai lần làm cho việc đóng gói thêm mong muốn. YMMV
ronen

Ok vì vậy tôi có thể dày nhưng vì vậy bạn không phải chỉ định 'selector'hai lần, (như được đề cập bởi @ronen), bạn không thể sử dụng object.parent().find('selector')??? - điều đó được nói rằng tôi thích ý tưởng về một lib làm điều đó cho bạn.
Sam

8
@ Circa1983 object.parent().find('selector')bao gồm anh chị em ruột objectvà con cháu của họ.
Robert

41

Bạn không thể làm điều này trực tiếp, gần nhất tôi có thể nghĩ đến là sử dụng .andSelf()và gọi .filter(), như thế này:

$(selector).find(oSelector).andSelf().filter(oSelector)
//or...
$(selector).find('*').andSelf().filter(oSelector);

Thật không may .andSelf(), không có một bộ chọn, sẽ rất hữu ích.


7
Bạn thậm chí đã thêm một nhận xét vào trang jquery ngay sau khi trả lời câu hỏi này api.jquery.com/andSelf/#comment-50124533 Bây giờ đó là sự thấu đáo. Đẹp! Tôi đã rất siêng năng và 'Thích' cái đó nữa.
John K

2
Cái thứ hai sẽ chậm chạp. Đầu tiên chỉ đơn giản là chậm.
Tgr

@Tgr - Tôi không đồng ý, mặc dù là người đầu tiên không nên cho thấy, trừ khi bạn đang làm việc với một rất nhiều yếu tố. Nếu bạn không cần xâu chuỗi, bạn có thể bỏ qua việc lọc lại các yếu tố đó cho chắc chắn.
Nick Craver

3
Thật thú vị, closest(..)bao gồm phần tử DOM hiện tại và lên cây trong khi tất cả các phương thức truyền tải xuống dưới cây như find(..)vv không khớp với phần tử hiện tại. Như thể nhóm jQuery cố tình thực hiện những điều này để không trùng lặp khi cả hai hoạt động được sử dụng cùng nhau cho một tìm kiếm dọc đầy đủ.
John K

17
Hãy nhớ rằng .andSelf () đã bị từ chối kể từ v1.8 và được thay thế bằng .addBack () lấy bộ chọn làm đối số. Xem api.jquery.com/addBack
kkara

9

Định nghĩa

$.fn.findSelf = function(selector) {
    var result = this.find(selector);
    this.each(function() {
        if ($(this).is(selector)) {
            result.add($(this));
        }
    });
    return result;
};

sau đó sử dụng

$.findSelf(selector);

thay vì

$find(selector);

Đáng buồn là jQuery không tích hợp sẵn. Thực sự kỳ lạ cho rất nhiều năm phát triển. Trình xử lý AJAX của tôi không được áp dụng cho một số phần tử hàng đầu do cách .find () hoạt động.


Đây là lỗi. Nó thêm tất cả "cái tôi", ngay cả khi chỉ một trong số chúng khớp với ... - Một lý do cho lỗi này là một phương thức jQuery có tên điên rồ ...
Robert Siemer

Tôi đã cố gắng sửa lỗi bạn đã báo cáo. Nó hoạt động đúng bây giờ?
Dmitriy Sintsov

Hầu hết các câu trả lời khác sử dụng filter()ở đó, mà có ý nghĩa hơn.
Robert Siemer

5
$('selector').find('otherSelector').add($('selector').filter('otherSelector'))

Bạn có thể lưu trữ $('selector')trong một biến để tăng tốc. Bạn thậm chí có thể viết một chức năng tùy chỉnh cho việc này nếu bạn cần nó rất nhiều:

$.fn.andFind = function(expr) {
  return this.find(expr).add(this.filter(expr));
};

$('selector').andFind('otherSelector')

Điều này chỉ hoạt động nếu bạn bắt đầu với một bộ chọn mặc dù, có thể không phải là trường hợp. Ngoài ra, nó không chính xác, nó sẽ là $('selector').find('otherSelector').add($('otherSelector')), những gì bạn có bây giờ tương đương với .andSelf(). Cuối cùng, .andFind()bộ lọc không dựa trên biểu thức, bạn sẽ cần .add($(this).filter(expr)):)
Nick Craver

@Nick Craver: yeah, tôi đã quên phần lọc, đã sửa bây giờ. Sẽ không có vấn đề gì nếu $('selector')được thay thế bằng một số phương pháp khác để lấy đối tượng jQuery (nếu đó là ý bạn không bắt đầu với bộ chọn), add()có thể xử lý mọi thứ $()có thể.
Tgr

Quan điểm của tôi là bạn $('selector')có thể là $('selector').children('filter').closest('.class').last()... nó có thể nằm trong một chuỗi và bạn không biết đối tượng bạn đang thêm là gì, vì vậy giải pháp chung nên lấy đối tượng trước đó giống như bộ lọc :)
Nick Craver

Tôi vẫn không thấy lý do tại sao điều đó sẽ là một vấn đề. thislà bất cứ đối tượng jQuery nào mà một plugin được gọi. Nó cũng có thể là kết quả của một chuỗi cuộc gọi.
Tgr

5

Câu trả lời được chấp nhận là rất không hiệu quả và lọc tập hợp các yếu tố đã được khớp.

//find descendants that match the selector
var $selection = $context.find(selector);
//filter the parent/context based on the selector and add it
$selection = $selection.add($context.filter(selector);

3

Nếu bạn muốn chuỗi hoạt động đúng, hãy sử dụng đoạn trích dưới đây.

$.fn.findBack = function(expr) {
    var r = this.find(expr);
    if (this.is(expr)) r = r.add(this);
    return this.pushStack(r);
};

Sau khi gọi hàm kết thúc, nó trả về phần tử #foo.

$('#foo')
    .findBack('.red')
        .css('color', 'red')
    .end()
    .removeAttr('id');

Không xác định bổ sung, bạn bị mắc kẹt với điều này.

$('#foo')
    .find('.red')
        .addBack('.red')
            .css('color', 'red')
        .end()
    .end()
    .removeAttr('id');

À, không ... Nếu thiscó nhiều hơn một yếu tố this.is()đã được thỏa mãn nếu chỉ một trong số chúng khớp.
Robert Siemer

3

Trong trường hợp bạn đang tìm kiếm chính xác một yếu tố , hoặc yếu tố hiện tại hoặc một yếu tố bên trong nó, bạn có thể sử dụng:

result = elem.is(selector) ? elem : elem.find(selector);

Trong trường hợp bạn đang tìm kiếm nhiều yếu tố bạn có thể sử dụng:

result = elem.filter(selector).add(elem.find(selector));

Việc sử dụng andSelf/ andBacklà khá hiếm, không biết tại sao. Có lẽ vì vấn đề hiệu suất mà một số kẻ đã đề cập trước tôi.

(Bây giờ tôi nhận thấy rằng Tgr đã đưa ra giải pháp thứ hai đó)


2

Tôi biết đây là một câu hỏi cũ, nhưng có một cách chính xác hơn. Nếu thứ tự là quan trọng, ví dụ như khi bạn khớp với bộ chọn như thế :first, tôi đã viết lên một hàm nhỏ sẽ trả về kết quả chính xác giống như find()thực sự bao gồm tập hợp các phần tử hiện tại:

$.fn.findAll = function(selector) {
  var $result = $();

  for(var i = 0; i < this.length; i++) {
    $result = $result.add(this.eq(i).filter(selector));
    $result = $result.add(this.eq(i).find(selector));
  }

  return $result.filter(selector);
};

Nó sẽ không hiệu quả bằng bất kỳ phương tiện nào, nhưng đó là cách tốt nhất tôi nghĩ ra để duy trì trật tự đúng đắn.


1

Tôi nghĩ andSelflà những gì bạn muốn:

obj.find(selector).andSelf()

Lưu ý rằng điều này sẽ luôn thêm lại nút hiện tại, cho dù nó có khớp với bộ chọn hay không.


1

Nếu bạn đang nghiêm túc tìm kiếm trong (các) nút hiện tại, bạn chỉ cần làm

$(html).filter('selector')

0

Tôi đã cố gắng tìm một giải pháp không lặp lại (nghĩa là không nhập cùng một bộ chọn hai lần).

Và phần mở rộng jQuery nhỏ này thực hiện điều đó:

jQuery.fn.findWithSelf = function(...args) {
  return this.pushStack(this.find(...args).add(this.filter(...args)));
};

Nó kết hợp find()(chỉ con cháu) với filter()(chỉ bộ hiện tại) và hỗ trợ bất kỳ đối số nào cả hai ăn. Các pushStack()cho phép .end()làm việc như mong đợi.

Sử dụng như thế này:

$(element).findWithSelf('.target')

-2

Đây là sự thật đúng (nhưng buồn):

$(selector).parent().find(oSelector).filter($(selector).find('*'))

http://jsfiddle.net/SergeJcqmn/MeQb8/2/


tuy nhiên, không hoạt động với các nút tách rời (và chính tài liệu).
John Dvorak

2
Uh, không, điều này sẽ $(selector)tự xóa khỏi tập hợp trong mọi trường hợp.
John Dvorak
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.