Lấy chỉ số của phần tử là con so với cha mẹ


160

Hãy nói rằng tôi có đánh dấu này:

<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Và tôi có jQuery này:

$("#wizard li").click(function () {
    // alert index of li relative to ul parent
});

Làm thế nào tôi có thể có được chỉ số của đứa trẻ liso với cha mẹ của nó, khi nhấp vào đó li?

Ví dụ: khi bạn nhấp vào "Bước 1", một alert"0" sẽ bật lên.

Câu trả lời:


247
$("#wizard li").click(function () {
    console.log( $(this).index() );
});

Tuy nhiên, thay vì đính kèm một trình xử lý nhấp chuột cho mỗi mục danh sách, tốt hơn là sử dụng (hiệu suất khôn ngoan) để sử dụng delegatenhư sau:

$("#wizard").delegate('li', 'click', function () {
    console.log( $(this).index() );
});

Trong jQuery 1.7+, bạn nên sử dụng on. Ví dụ dưới đây liên kết sự kiện với thành #wizardphần, hoạt động như một sự kiện dành cho đại biểu:

$("#wizard").on("click", "li", function() {
    console.log( $(this).index() );
});

3
xin chào redsapes .. Tôi đang thực hành với jQuery, tôi không biết gì về đại biểu: D .. tại sao ủy nhiệm lại tốt hơn là đính kèm các sự kiện trực tiếp vào các yếu tố?
stecb

1
@steweb - Hey - bởi vì một trình xử lý sự kiện được ưu tiên hơn nhiều so với tiềm năng. Việc đính kèm các sự kiện vào dom có ​​thể tốn kém nếu bạn có danh sách lớn vì vậy theo quy tắc tôi cố gắng sử dụng ở trên nếu có thể thay vì xử lý riêng lẻ trên mỗi thành phần. Một bài viết mà đi sâu hơn là briancrescimanno.com/2008/05/19/... - cũng google 'đoàn sự kiện javascript'
redsquare

ok, vì vậy, quản lý các sự kiện theo cách này là một cái gì đó nhẹ hơn so với 'tệp đính kèm dom' cổ điển :) .. cảm ơn!
stecb

@steweb - Nó cũng nhẹ hơn vì jquery không cần thực hiện tra cứu ban đầu tất cả các yếu tố li. Nó chỉ tra cứu container và lắng nghe ở mức đó để xem đối tượng được nhấp có phải là li hay không.
redsapes

Phương pháp .index này siêu hữu ích với tôi. Tôi đang sử dụng jQuery Sortable để sắp xếp, nhưng nó lưu trữ thông tin xếp hạng ngữ nghĩa trong DOM. Với .index (), tôi có thể kéo bảng xếp hạng ra khỏi dom thực sự sạch sẽ. Cảm ơn!
SimplGy

41

cái gì đó như:

$("ul#wizard li").click(function () {
  var index = $("ul#wizard li").index(this);
  alert("index is: " + index)
});

9
Bổ sung tuyệt vời - chúng ta có thể tìm thấy chỉ mục tương đối cho bộ chọn cha. +1
BasTaller

1
thích câu trả lời này vì nó thực sự trả lời câu hỏi hơn là một giải pháp khả thi cho ví dụ
DarkMukke

8

Hãy xem ví dụ này .

$("#wizard li").click(function () {
    alert($(this).index()); // alert index of li relative to ul parent
});

4

Không cần phải có một thư viện lớn như jQuery để thực hiện điều này, nếu bạn không muốn. Để đạt được điều này với thao tác DOM tích hợp, hãy lấy một tập hợp các lianh chị em trong một mảng và khi nhấp vào, hãy kiểm tra indexOfphần tử được nhấp trong mảng đó.

const lis = [...document.querySelectorAll('#wizard > li')];
lis.forEach((li) => {
  li.addEventListener('click', () => {
    const index = lis.indexOf(li);
    console.log(index);
  });
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Hoặc, với đoàn sự kiện:

const lis = [...document.querySelectorAll('#wizard li')];
document.querySelector('#wizard').addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li> which is a child of wizard:
  if (!target.matches('#wizard > li')) return;
  
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>

Hoặc, nếu các phần tử con có thể thay đổi linh hoạt (như với danh sách việc cần làm), thì bạn sẽ phải xây dựng mảng lis trên mỗi lần nhấp, thay vì trước đó:

const wizard = document.querySelector('#wizard');
wizard.addEventListener('click', ({ target }) => {
  // Make sure the clicked element is a <li>
  if (!target.matches('li')) return;
  
  const lis = [...wizard.children];
  const index = lis.indexOf(target);
  console.log(index);
});
<ul id="wizard">
    <li>Step 1</li>
    <li>Step 2</li>
</ul>


$ (...). indexOf không phải là một chức năng
Kareem

2
Không có đoạn mã nào trong câu trả lời của tôi tạo ra lỗi đó - bạn có thể nhấn "Chạy đoạn mã" để xem chúng hoạt động. Nếu bạn gặp phải lỗi đó, bạn đang sử dụng mã khác - có vẻ như bạn đang sử dụng jQuery, nhưng câu trả lời của tôi là chỉ ra cách thực hiện loại điều này mà không cần jQuery
SurePerformance

Đủ công bằng. Vâng, tôi đang sử dụng JQuery. Cảm ơn
Kareem

3

Delegate và Live rất dễ sử dụng nhưng nếu bạn không có thêm li: s, bạn có thể sử dụng delagation sự kiện với liên kết / nhấp chuột bình thường. Cần có một số hiệu suất đạt được bằng cách sử dụng phương pháp này vì DOM sẽ không phải được theo dõi đối với các yếu tố phù hợp mới. Không có con số thực tế nào nhưng nó có ý nghĩa :)

$("#wizard").click(function (e) {
    var source = $(e.target);
    if(source.is("li")){
        // alert index of li relative to ul parent
        alert(source.index());
    }
});

Bạn có thể kiểm tra nó tại jsFiddle: http://jsfiddle.net/jimmysv/4Sfdh/1/


1
Bạn đang đề cập đến điều gì khi bạn nói điều này 'DOM sẽ không phải theo dõi'? đại biểu jq không theo dõi dom.
redsapes

@redsapes Tôi đã có ấn tượng rằng Delegate chỉ là một biến thể hiệu quả hơn của Live. Đây là từ api.jquery.com/delegate : "Đính kèm trình xử lý với một hoặc nhiều sự kiện cho tất cả các phần tử khớp với bộ chọn, bây giờ hoặc trong tương lai, dựa trên một bộ phần tử gốc cụ thể." Nó phải được theo dõi để ràng buộc trong tương lai?
jimmystormig

Không, nó chỉ sử dụng ủy quyền trên container như mã của bạn ở trên. Nếu bạn chèn một phần tử li mới vào vùng chứa, sự kiện nhấp vào vùng chứa vẫn được kích hoạt và mọi thứ vẫn hoạt động. Không cần giám sát.
redsapes

@redsapes Vâng, bạn đã đúng. Giải pháp của tôi hoạt động ngay cả khi có các yếu tố mới được thêm vào sau khi DOM được tải. Vì Delegate sử dụng Live trong nội bộ (xem stackoverflow.com/questions/2954932/, ) nên vẫn có cảm giác như điều này được tối ưu hóa hơn nhưng ít thuận tiện hơn. Nhưng như tôi đã nói, tôi không có số.
jimmystormig

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.