API HTML

Trong phần giới thiệu về loạt bài này, có viết "Các phần tử HTML là các nút tạo nên Mô hình đối tượng tài liệu". Chúng ta đã thảo luận về loại nút phần tử. Trong phần này, chúng ta sẽ thảo luận về các API phần tử cho phép truy vấn các nút đó.

DOM và AOM

DOM là một API để truy cập và thao tác với tài liệu. DOM là cây của tất cả các nút trong tài liệu. Một số nút có thể có nút con, một số khác thì không. Cây này bao gồm các phần tử, cùng với các thuộc tính và nút văn bản.

Cây nút MLW hiển thị các phần tử và nút văn bản.

Các công cụ trình duyệt không cung cấp hình ảnh trực quan dạng cây như hình trên, nhưng bạn có thể thấy các nút trong trình kiểm tra phần tử.

DOM/ARIA.

Cây hỗ trợ tiếp cận là cách trình bày dạng cây có thể được kiểm tra trong các công cụ dành cho nhà phát triển trình duyệt. AOM dựa trên DOM; tương tự, cây hỗ trợ tiếp cận chứa các đối tượng đại diện cho tất cả các phần tử đánh dấu, thuộc tính và nút văn bản:

Ví dụ về AOM.

API phần tử HTML

Chữ cái ở giữa của DOM là "object" (đối tượng). Giống như ví dụ về đối tượng person hoặc car trong hầu hết các lớp học nhập môn về lập trình hướng đối tượng, mọi nút trong cây tài liệu đều là một đối tượng có thể được thao tác bằng JavaScript.

Trình duyệt cung cấp nhiều API cung cấp các phương thức, sự kiện và truy vấn cũng như cập nhật thuộc tính được hỗ trợ gốc. Các nút phần tử chứa thông tin về tất cả các thuộc tính được đặt trên phần tử. Bạn có thể sử dụng giao diện HTML để truy cập vào thông tin về các thuộc tính của một phần tử. Ví dụ: chúng ta có thể sử dụng HTMLImageElement.alt để lấy các thuộc tính alt của tất cả hình ảnh:

let allImages = document.querySelectorAll('img');
allImages.forEach((imageInstance) => {
  console.log(imageInstance.alt);
});

Giao diện HTML không chỉ cung cấp quyền truy cập vào các thuộc tính của một phần tử mà bạn còn có thể truy cập vào nhiều thông tin khác. Chúng ta có thể tìm thấy HTMLElement.offsetHeight chỉ có thể đọc để lấy chiều cao của từng phần trong trang, tương ứng với bố cục.

let allSections = document.querySelectorAll('section');
allSections.forEach((sectionInstance) => {
  console.log(sectionInstance.offsetHeight);
});

Nếu người dùng thay đổi hướng thiết bị hoặc thay đổi chiều rộng của khung nhìn, chiều cao của mỗi <section> sẽ thay đổi và các thuộc tính DOM sẽ tự động cập nhật theo chiều cao đó.

API giao diện HTML không chỉ giới hạn ở việc truy cập vào các giá trị thuộc tính. DOM cung cấp thông tin chi tiết về trạng thái hiện tại của giao diện người dùng. API HTML có thể truy cập vào tất cả thông tin đó. Bạn có thể truy cập vào thời lượng của video, vị trí của một lượt xem trong quá trình phát hiện tại, và liệu video (hoặc âm thanh) đã phát xong hay chưa bằng HTMLMediaElement.duration, HTMLMediaElement.currentTimeHTMLMediaElement.ended tương ứng.

Các giao diện phần tử có sẵn

Hầu hết các phần tử HTML mà chúng ta đã đề cập đến trong loạt bài này và chưa đề cập đến, ngoài một số phần tử phân đoạn, đều có giao diện DOM liên kết. Giao diện cơ sở cho tất cả các phần tử được đặt tên một cách thích hợp là Element (Phần tử). HTMLElement kế thừa từ Phần tử và tất cả giao diện dành riêng cho phần tử HTML kế thừa từ phần tử này. Một số giao diện dành riêng cho phần tử được triển khai bằng nhiều phần tử tương tự.

Các giao diện bao gồm:

Quy ước đặt tên là "HTML", theo sau là một phần tử hoặc nhóm phần tử viết hoa kiểu camel, theo sau là "Phần tử", nhưng phần tử hoặc nhóm phần tử không tuân theo mẫu chính xác. Đừng lo. Bạn không cần phải ghi nhớ những điều này. Điều quan trọng là bạn phải biết rằng các tệp này tồn tại để bạn có thể tra cứu khi cần.

Nếu bạn có một tập hợp các phần tử, thì cũng có một số giao diện tập hợp. Ví dụ: phương thức HTMLCollection.namedItem() trả về phần tử đầu tiên trong tập hợp có thuộc tính id hoặc name khớp với tham số hoặc rỗng nếu không có phần tử nào khớp.

Hơn 30 phần tử không có giao diện DOM được liên kết ngoài HTMLElement, bao gồm <address>, <article>, <section>, <nav>, <header>, <footer>, <aside><hgroup>. Nhiều phần tử không hỗ trợ bất kỳ thuộc tính nào không còn được dùng nữa, không phải thuộc tính toàn cục có giao diện dành riêng cho phần tử, chẳng hạn như HTMLPElement (phần tử <p>) và HTMLUnknownElement (<😃> hoặc bất kỳ phần tử nào khác không được xác định), nhưng các giao diện đó không triển khai bất kỳ thuộc tính hoặc phương thức bổ sung nào ngoài các thuộc tính và phương thức kế thừa từ HTMLElement và không được liệt kê ở trên.

Các phương thức và thuộc tính API thừa

Nếu một giao diện có cùng tên phương thức hoặc thuộc tính với giao diện mà giao diện đó kế thừa, thì phương thức hoặc thuộc tính kế thừa sẽ ghi đè phương thức hoặc thuộc tính được kế thừa. Nói cách khác, các phương thức và thuộc tính mẹ sẽ ghi đè các phương thức và thuộc tính con. Khi chúng ta truy cập vào các thuộc tính altoffsetHeight trong API Phần tử HTML với imageInstance.altsectionInstance.offsetHeight tương ứng, mã không xác định được API nào đang được truy cập. Nói chung, như với hai ví dụ này, đây không phải là vấn đề.

Tuy nhiên, có một số trường hợp dư thừa có thể gây ra sự cố. Ví dụ: HTMLCollection.length chỉ có thể đọc, trong khi giao diện kế thừa HTMLOptionsCollection có thuộc tính độ dài (chỉ được trả về bởi thuộc tính options của <select>) với quyền đọc và ghi. Bạn có thể dùng HTMLOptionsCollection để đặt kích thước bộ sưu tập.

Các giao diện khác

Có các giao diện bổ sung cho phép thao tác với vị trí nhánh của các nút DOM. Giao diện EventTarget cung cấp cho chúng ta addEventListener()removeEventListener(), được kế thừa bởi các giao diện NodeWindow. Đổi lại, giao diện Element, Document và DocumentFragment (mà chúng ta đã thấy trong thành phần tuỳ chỉnh) kế thừa từ Node và giao diện HTMLElement kế thừa từ Element.

Giao diện node

Mỗi loại nút DOM được biểu thị bằng một giao diện dựa trên Node, giao diện này cung cấp thông tin và phương thức dưới dạng các phần tử liên quan đến cây DOM. Giao diện Node cho phép truy vấn và thêm nút vào cây nút.

Hàm "đi qua DOM" nổi tiếng của Douglas Crockford sử dụng các thuộc tính firstChildnextSibling của Node.

const walk_the_DOM = function walk(node, callback) {
  callback(node);
  node = node.firstChild;
  while (node) {
    walk(node, callback);
    node = node.nextSibling;
  }
};

Chúng ta đã sử dụng các phương thức appendChild()cloneNode() của Node để xác định các phần tử tuỳ chỉnh. Giao diện Nút cung cấp nhiều thuộc tính và phương thức hữu ích để truy vấn và thao tác với DOM.

customElements.define('star-rating',
  class extends HTMLElement {
    constructor() {
      super(); // Always call super first in constructor
      const starRating = document.getElementById('star-rating-template').content;
      const shadowRoot = this.attachShadow({
        mode: 'open'
      });
      shadowRoot.appendChild(starRating.cloneNode(true));
    }
  });

Phương thức attachShadow() là một phương thức của giao diện Element. Ngoài ra, còn có giao diện shadowRoot cho Shadow DOM API được hiển thị riêng biệt với cây DOM chính của tài liệu.

Giao diện DocumentHTMLDocument

Giao diện Document kế thừa từ Node. Thuộc tính này đại diện cho trang web được tải trong trình duyệt, cho dù tài liệu là HTML, SVG, XML, MathML hay loại khác. Giao diện Document cũng kế thừa từ giao diện HTMLDocument.

document cho phép truy cập nhanh vào các loại nút và khả năng tạo tập hợp các loại phần tử cụ thể, chẳng hạn như document.bodydocument.styleSheets. HTMLDocument cho phép truy cập thông tin liên quan đến tài liệu không có trong các nút HTML, chẳng hạn như Document.location, Document.lastModifiedDocument.Cookie.

Có một số API dựa trên các tính năng xuất hiện thông qua giao diện tài liệu, bao gồm API Kéo và thảAPI Toàn màn hình. Cả hai đều kế thừa từ Element.

Giao diện Window

Giao diện Window bao gồm các mục có sẵn trên toàn cầu ngoài DOM có thể dùng để thao tác với DOM. Window cung cấp các hàm, không gian tên, đối tượng và hàm khởi tạo được ghi lại trong JavaScriptTham chiếu DOM của MDN.

Giao diện Window là API cho đối tượng chứa tài liệu. Đối tượng window toàn cục là cửa sổ mà tập lệnh đang chạy. Mỗi thẻ trình duyệt đều chứa đối tượng Window riêng. Giao diện Cửa sổ có thể truy vấn nội dung của thẻ cũng như cửa sổ và thiết bị tổng thể. Ví dụ: bạn có thể sử dụng phương thức resizeTo() để đổi kích thước cửa sổ trình duyệt, thuộc tính devicePixelRatio cung cấp quyền truy cập vào các pixel hiển thị của thiết bị. Khi truy cập thông tin về thẻ chứa nội dung thay vì cây DOM mà thẻ hiển thị, cửa sổ có thể là giao diện mà bạn đang tìm kiếm.

Có một số API dựa trên các tính năng xuất hiện thông qua giao diện Cửa sổ, bao gồm cả API Web WorkerIndexedDB.

Kiểm tra mức độ hiểu biết

Kiểm tra kiến thức của bạn về API HTML.

O trong DOM có nghĩa là gì?

Có hướng.
Hãy thử lại.
Đối tượng.
Chính xác!
Bên ngoài.
Hãy thử lại.

Giao diện nào có thể giúp bạn tìm hiểu thông tin về thẻ chứa nội dung?

Cửa sổ
Chính xác!
Tài liệu
Hãy thử lại.
Nút
Hãy thử lại.