Quản lý thẻ

Tạo trình quản lý thẻ đầu tiên.

Tổng quan

Hướng dẫn này sẽ tạo một trình quản lý thẻ để sắp xếp các thẻ tài liệu về tiện ích Chrome và Cửa hàng Chrome trực tuyến.

Cửa sổ bật lên của tiện ích Trình quản lý thẻ
Tiện ích Trình quản lý thẻ

Trong hướng dẫn này, chúng tôi sẽ giải thích cách thực hiện những việc sau:

  • Tạo cửa sổ bật lên của tiện ích bằng API Action.
  • Truy vấn các thẻ cụ thể bằng API Tabs (Thẻ).
  • Bảo vệ quyền riêng tư của người dùng thông qua các quyền hạn chế của máy chủ lưu trữ.
  • Thay đổi tiêu điểm của thẻ.
  • Di chuyển các thẻ sang cùng một cửa sổ và nhóm các thẻ đó lại với nhau.
  • Đổi tên nhóm thẻ bằng API TabGroups.

Trước khi bắt đầu

Hướng dẫn này giả định rằng bạn có kinh nghiệm phát triển web cơ bản. Bạn nên xem bài viết Xin chào thế giới để tìm hiểu về quy trình phát triển tiện ích.

Tạo tiện ích

Để bắt đầu, hãy tạo một thư mục mới có tên tabs-manager để lưu trữ các tệp của tiện ích. Nếu muốn, bạn có thể tải mã nguồn đầy đủ xuống trên GitHub.

Bước 1: Thêm dữ liệu và biểu tượng tiện ích

Tạo một tệp có tên là manifest.json và thêm mã sau:

{
  "manifest_version": 3,
  "name": "Tab Manager for Chrome Dev Docs",
  "version": "1.0",
  "icons": {
    "16": "images/icon-16.png",
    "32": "images/icon-32.png",
    "48": "images/icon-48.png",
    "128": "images/icon-128.png"
  }
}

Để tìm hiểu thêm về các khoá tệp kê khai này, hãy xem hướng dẫn về Thời gian đọc. Hướng dẫn này giải thích chi tiết hơn về siêu dữ liệubiểu tượng của tiện ích.

Tạo thư mục images rồi tải biểu tượng xuống vào thư mục đó.

Bước 2: Tạo và tạo kiểu cho cửa sổ bật lên

API Action (Hành động) kiểm soát hành động của tiện ích (biểu tượng thanh công cụ). Khi người dùng nhấp vào thao tác của tiện ích, thao tác đó sẽ chạy một số mã hoặc mở một cửa sổ bật lên, như trong trường hợp này. Bắt đầu bằng cách khai báo cửa sổ bật lên trong manifest.json:

{
  "action": {
    "default_popup": "popup.html"
  }
}

Cửa sổ bật lên tương tự như một trang web, ngoại trừ một điểm: cửa sổ này không thể chạy JavaScript cùng dòng. Tạo tệp một popup.html rồi thêm đoạn mã sau:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./popup.css" />
  </head>
  <body>
    <template id="li_template">
      <li>
        <a>
          <h3 class="title">Tab Title</h3>
          <p class="pathname">Tab Pathname</p>
        </a>
      </li>
    </template>

    <h1>Google Dev Docs</h1>
    <button>Group Tabs</button>
    <ul></ul>

    <script src="./popup.js" type="module"></script>
  </body>
</html>

Tiếp theo, bạn sẽ tạo kiểu cho cửa sổ bật lên. Tạo tệp một popup.css rồi thêm đoạn mã sau:

body {
  width: 20rem;
}

ul {
  list-style-type: none;
  padding-inline-start: 0;
  margin: 1rem 0;
}

li {
  padding: 0.25rem;
}
li:nth-child(odd) {
  background: #80808030;
}
li:nth-child(even) {
  background: #ffffff;
}

h3,
p {
  margin: 0;
}

Bước 3: Quản lý các thẻ

Tabs API cho phép một tiện ích tạo, truy vấn, sửa đổi và sắp xếp lại các thẻ trong trình duyệt.

Yêu cầu cấp quyền

Bạn có thể sử dụng nhiều phương thức trong Tabs API mà không cần yêu cầu quyền. Tuy nhiên, chúng ta cần quyền truy cập vào titleURL của các thẻ; các thuộc tính nhạy cảm này yêu cầu quyền. Chúng ta có thể yêu cầu quyền "tabs", nhưng điều này sẽ cấp quyền truy cập vào các thuộc tính nhạy cảm của tất cả thẻ. Vì chỉ quản lý các thẻ của một trang web cụ thể, nên chúng ta sẽ yêu cầu cấp quyền hẹp cho máy chủ lưu trữ.

Việc thu hẹp quyền của máy chủ lưu trữ cho phép chúng tôi bảo vệ quyền riêng tư của người dùng bằng cách cấp quyền nâng cao cho các trang web cụ thể. Thao tác này sẽ cấp quyền truy cập vào các thuộc tính titleURL, cũng như các chức năng bổ sung. Thêm mã được làm nổi bật vào tệp manifest.json:

{
  "host_permissions": [
    "https://developer.chrome.com/*"
  ]
}

💡 Đâu là những điểm khác biệt chính giữa quyền đối với thẻ và quyền đối với máy chủ lưu trữ?

Cả quyền "tabs" và quyền của máy chủ đều có những hạn chế.

Quyền "tabs" cấp cho tiện ích khả năng đọc dữ liệu nhạy cảm trên tất cả các thẻ. Theo thời gian, thông tin này có thể được dùng để thu thập nhật ký duyệt web của người dùng. Do đó, nếu bạn yêu cầu quyền này, Chrome sẽ hiển thị thông báo cảnh báo sau đây tại thời điểm cài đặt:

Hộp thoại cảnh báo về quyền đối với thẻ

Quyền từ phía máy chủ cho phép tiện ích đọc và truy vấn các thuộc tính nhạy cảm của thẻ trùng khớp, đồng thời chèn tập lệnh vào các thẻ này. Người dùng sẽ thấy thông báo cảnh báo sau đây tại thời điểm cài đặt:

Hộp thoại cảnh báo về quyền lưu trữ

Những cảnh báo này có thể gây lo ngại cho người dùng. Để mang lại trải nghiệm làm quen tốt hơn, bạn nên triển khai các quyền không bắt buộc.

Truy vấn các thẻ

Bạn có thể truy xuất các thẻ từ các URL cụ thể bằng phương thức tabs.query(). Tạo tệp popup.js rồi thêm mã sau:

const tabs = await chrome.tabs.query({
  url: [
    "https://developer.chrome.com/docs/webstore/*",
    "https://developer.chrome.com/docs/extensions/*",
  ]
});

💡 Tôi có thể sử dụng API Chrome trực tiếp trong cửa sổ bật lên không?

Một cửa sổ bật lên và các trang tiện ích khác có thể gọi bất kỳ API Chrome nào vì các trang này được phân phát từ giản đồ chrome. Ví dụ: chrome-extension://EXTENSION_ID/popup.html.

Đặt tiêu điểm vào một thẻ

Trước tiên, tiện ích này sẽ sắp xếp tên thẻ (tiêu đề của các trang HTML có trong đó) theo thứ tự bảng chữ cái. Sau đó, khi người dùng nhấp vào một mục trong danh sách, mục đó sẽ tập trung vào thẻ đó bằng tabs.update() và đưa cửa sổ lên trước bằng windows.update(). Thêm mã sau vào tệp popup.js:

...
const collator = new Intl.Collator();
tabs.sort((a, b) => collator.compare(a.title, b.title));

const template = document.getElementById("li_template");
const elements = new Set();
for (const tab of tabs) {
  const element = template.content.firstElementChild.cloneNode(true);

  const title = tab.title.split("-")[0].trim();
  const pathname = new URL(tab.url).pathname.slice("/docs".length);

  element.querySelector(".title").textContent = title;
  element.querySelector(".pathname").textContent = pathname;
  element.querySelector("a").addEventListener("click", async () => {
    // need to focus window as well as the active tab
    await chrome.tabs.update(tab.id, { active: true });
    await chrome.windows.update(tab.windowId, { focused: true });
  });

  elements.add(element);
}
document.querySelector("ul").append(...elements);
...

💡 JavaScript thú vị được dùng trong mã này

  • Collator dùng để sắp xếp mảng thẻ theo ngôn ngữ ưu tiên của người dùng.
  • Thẻ mẫu dùng để xác định một phần tử HTML có thể được sao chép thay vì sử dụng document.createElement() để tạo từng mục.
  • Hàm khởi tạo URL dùng để tạo và phân tích cú pháp URL.
  • Cú pháp truyền dữ liệu dùng để chuyển đổi Tập hợp các phần tử thành đối số trong lệnh gọi append().

Nhóm các thẻ

API TabGroups cho phép tiện ích đặt tên cho nhóm và chọn màu nền. Thêm quyền "tabGroups" vào tệp kê khai bằng cách thêm mã được làm nổi bật:

{
  "permissions": [
    "tabGroups"
  ]
}

Trong popup.js, hãy thêm mã sau để tạo một nút sẽ nhóm tất cả các thẻ bằng tabs.group() và chuyển các thẻ đó vào cửa sổ hiện tại.

const button = document.querySelector("button");
button.addEventListener("click", async () => {
  const tabIds = tabs.map(({ id }) => id);
  if (tabIds.length) {
    const group = await chrome.tabs.group({ tabIds });
    await chrome.tabGroups.update(group, { title: "DOCS" });
  }
});

Kiểm thử để đảm bảo tính năng này hoạt động

Xác minh rằng cấu trúc tệp của dự án khớp với cây thư mục sau:

Nội dung của thư mục trình quản lý thẻ: manifest.json, popup.js, popup.css, popup.html và thư mục hình ảnh.

Tải tiện ích trên máy

Để tải một tiện ích chưa giải nén ở chế độ nhà phát triển, hãy làm theo các bước trong phần Hello World.

Mở một vài trang tài liệu

Mở các tài liệu sau trong các cửa sổ khác nhau:

Nhấp vào cửa sổ bật lên. Ứng dụng sẽ hiển thị như sau:

Cửa sổ bật lên của tiện ích Trình quản lý thẻ
Cửa sổ bật lên của tiện ích Trình quản lý thẻ

Nhấp vào nút "Nhóm thẻ". Ứng dụng sẽ hiển thị như sau:

Thẻ được nhóm trong Trình quản lý thẻ
Nhóm các thẻ bằng tiện ích Trình quản lý thẻ

🎯 Các điểm cải tiến tiềm năng

Dựa trên những gì bạn đã học được hôm nay, hãy thử triển khai một trong những cách sau:

  • Tuỳ chỉnh trang tính kiểu của cửa sổ bật lên.
  • Thay đổi màu và tiêu đề của nhóm thẻ.
  • Quản lý các thẻ của một trang web tài liệu khác.
  • Thêm tính năng hỗ trợ để huỷ nhóm các thẻ đã nhóm.

Hãy tiếp tục xây dựng!

Chúc mừng bạn đã hoàn thành hướng dẫn này 🎉. Hãy tiếp tục phát triển kỹ năng của bạn bằng cách hoàn thành các hướng dẫn khác trong loạt bài viết này:

Phần mở rộng Kiến thức bạn sẽ học được
Thời gian đọc Để tự động chèn một phần tử trên mọi trang.
Chế độ lấy nét Để chạy mã trên trang hiện tại sau khi nhấp vào hành động của tiện ích.

Tiếp tục khám phá

Chúng tôi hy vọng bạn đã có trải nghiệm thú vị khi xây dựng tiện ích Chrome này và rất mong được tiếp tục hành trình tìm hiểu về việc phát triển Chrome cùng bạn. Bạn nên tham khảo lộ trình học tập sau: