Chào bạn! Khi làm việc với DOM, đôi lúc bạn cần đi lên (ngược) từ một phần tử để tìm các thành phần parents (ancestors) như div cha, hoặc đi xuống (xuôi) để tìm các phần tử con (descendants) như li, p trong nội dung HTML.

jQuery cung cấp những phương thức traversing cực kỳ mạnh mẽ để giúp bạn di chuyển qua cây DOM một cách đơn giản, nhanh chóng và chính xác.

Trong bài viết này, chúng ta sẽ cùng tìm hiểu:

  • Các phương thức traversing Ancestors (parent(), parents(), parentsUntil())
  • Các phương thức traversing Descendants (children(), find())
  • Kèm theo ví dụ minh họa thực tế để bạn dễ dàng áp dụng vào dự án của mình.

1. Traversing Ancestors

Traversing ancestors nghĩa là đi từ một phần tử con lên các phần tử cha trong cây DOM.

1.1. parent()

  • Trả về phần tử cha trực tiếp (immediate parent).
  • Nếu cần tìm phần tử cha ở ngay trên.

Cú pháp:

js
$(selector).parent();

Ví dụ:

html
<div class="container">
  <div class="box">
    <p>Hello World</p>
  </div>
</div>

<script>
$(document).ready(function(){
  $("p").parent().css("border", "2px solid red");
});
</script>

Giải thích: đoạn code sẽ thêm border đỏ cho div.box, vì đó là parent của p.

1.2. parents()

  • Trả vềtất cả tổ tiên của phần tử được chọn (không giới hạn cấp).
  • Có thể truyền tham số để lọc theo selector.

Cú pháp:

js
$(selector).parents();
$(selector).parents(filter);

Ví dụ:

html
<div class="container">
  <div class="box">
    <p>Hello World</p>
  </div>
</div>

<script>
$(document).ready(function(){
  $("p").parents(".container").css("background", "lightblue");
});
</script>

Giải thích: đoạn code sẽ tô màu nền xanh nhạt cho div.container, vì nó là tổ tiên của p có class .container.

1.3. parentsUntil()

  • Đi lên qua các ancestor nhưng dừng lại trước phần tử được chỉ định.
  • Không bao gồm phần tử giới hạn.

Cú pháp:

js
$(selector).parentsUntil(stop);

Ví dụ:

html
<div class="grandparent">
  <div class="parent">
    <div class="child">Child Div</div>
  </div>
</div>

<script>
$(document).ready(function(){
  $(".child").parentsUntil(".grandparent").css("border", "2px dashed green");
});
</script>

Giải thích: phần tử div.parent sẽ được viền dashed xanh, nhưng div.grandparent sẽ không bị ảnh hưởngparentsUntil() dừng ngay trước nó.

2. Traversing Descendants (Đi xuống phần tử con)

Traversing descendants nghĩa là đi từ phần tử cha tìm các phần tử con.

2.1. children()

  • Trả về tất cả các phần tử con trực tiếp của phần tử được chọn.
  • Có thể truyền tham số để lọc theo selector.

Cú pháp:

js
$(selector).children();
$(selector).children(filter);

Ví dụ:

html
<div class="parent">
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
  <span>Span 1</span>
</div>

<script>
$(document).ready(function(){
  $(".parent").children("p").css("color", "blue");
});
</script>

Giải thích: chỉ các p trực tiếp bên trong .parent mới được đổi màu xanh.

2.2. find()

  • Trả vềtất cả các phần tử con (bao gồm cả con cháu nhiều cấp).
  • Dùng để tìm kiếm sâu bên trong một cây DOM.

Cú pháp:

js
$(selector).find(selector);

Ví dụ:

html
<div class="parent">
  <div class="child">
    <p>Nested Paragraph</p>
  </div>
</div>

<script>
$(document).ready(function(){
  $(".parent").find("p").css("font-weight", "bold");
});
</script>

Giải thích:p nằm sâu bên trong .child vẫn được chọn và làm đậm chữ, nhờ find().

3. Bảng tổng hợp nhanh

Phương thứcMục đích
parent()Lấy phần tử cha trực tiếp
parents()Lấy tất cả tổ tiên
parentsUntil()Lấy ancestor cho đến một selector cụ thể
children()Lấy tất cả con trực tiếp
find()Tìm kiếm tất cả descendants phù hợp

4. Sơ đồ minh họa trực quan: Mối quan hệ Ancestor – Descendant

Hãy hình dung cấu trúc HTML như một cây gia đình:

shell
<div class="grandparent">
    └── <div class="parent">
          ├── <p>Paragraph 1</p>
          └── <span>Span 1</span>
    </div>
</div>
  • grandparentancestor của parent, p, và span.
  • parentancestor trực tiếp của pspan.
  • pspandescendants của parentgrandparent.
  • parent() đi từ p lên parent.
  • parents() đi từ p lên cả parentgrandparent.
  • parentsUntil() đi từ p lên tới (nhưng không bao gồm) grandparent.
  • children() từ parent sẽ tìm ra pspan.
  • find() từ grandparent sẽ tìm ra tất cả descendants bên trong.

📌 Lưu ý:

  • parent() chỉ 1 cấp.
  • parents() nhiều cấp.
  • children() chỉ lấy các phần tử con trực tiếp, không lấy cháu chắt.
  • find() tìm tất cả con cháu phù hợp.

5. Bài tập nhỏ thực hành

Hãy cùng luyện tập một bài tập nhỏ để hiểu sâu hơn:

HTML mẫu:

html
<div class="company">
  <div class="department">
    <div class="team">
      <p class="member">Alice</p>
      <p class="member">Bob</p>
    </div>
  </div>
</div>

Câu hỏi:

  1. Sử dụng parent(), tô viền đỏ cho team khi chọn p.member.
  2. Sử dụng parents(), thay đổi màu nền company khi chọn p.member.
  3. Sử dụng children(), đổi màu chữ tất cả p.member khi chọn team.
  4. Sử dụng find(), tìm tất cả p bên trong company và làm in đậm chữ.

Gợi ý cách làm:

js
$(document).ready(function(){
  // 1. parent()
  $(".member").parent().css("border", "2px solid red");

  // 2. parents()
  $(".member").parents(".company").css("background", "lightyellow");

  // 3. children()
  $(".team").children(".member").css("color", "green");

  // 4. find()
  $(".company").find("p").css("font-weight", "bold");
});

Kết bài

Hiểu rõ cách traversing ancestors và descendants trong jQuery sẽ giúp bạn:

  • Điều hướng DOM chính xác, hiệu quả.
  • Giảm lỗi và tối ưu hiệu suất website.
  • Xây dựng giao diện web động, phản hồi nhanh hơn.
  • Nhanh chóng tìm kiếm các phần tử liên quan.
  • Tối ưu hóa thao tác với cây DOM phức tạp.
  • Giảm thiểu việc phải viết nhiều vòng lặp hoặc thủ công tìm kiếm phần tử.

Việc thành thạo các phương thức như parent(), parents(), parentsUntil(), children(), và find() sẽ giúp bạn xây dựng các ứng dụng web tương tác mạnh mẽ và linh hoạt hơn rất nhiều.

Hãy thử thực hành thêm với các cây DOM phức tạp hơn để thuần thục kỹ năng traversing này nhé!