Quản lý thẻ

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

Tổng quan

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

Cửa sổ bật lên 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 một cửa sổ bật lên của tiện ích bằng cách sử dụng API Action.
  • Truy vấn các thẻ cụ thể bằng API Thẻ.
  • Bảo vệ quyền riêng tư của người dùng thông qua các quyền hạn hẹp của máy chủ.
  • Thay đổi tiêu điểm của thẻ.
  • Di chuyển các thẻ sang cùng một cửa sổ rồi nhóm lại.
  • Đổ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 Hello World để biết thông tin giới thiệ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 là 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 hoàn chỉnh xuống từ 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 rồi thêm đoạn 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 Thời gian đọc giải thích chi tiết hơn về siêu dữ liệucác biểu tượng của tiện ích.

Tạo thư mục images rồi tải các 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 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 này 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 nhưng có một ngoại lệ là 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ẻ

API Thẻ cho phép 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 API Tab mà không cần yêu cầu quyền nào. 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 tôi có thể yêu cầu quyền "tabs", nhưng quyền này sẽ cấp quyền truy cập vào thuộc tính nhạy cảm của tất cả thẻ. Vì chúng tôi chỉ quản lý các thẻ của một trang web cụ thể, nên chúng tôi sẽ yêu cầu quyền truy cập trên máy chủ để thu hẹp phạm vi quản lý.

Quyền của máy chủ ở mức hẹp 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 cấp 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 khả năng khác. Thêm mã được đánh dấu vào tệp manifest.json:

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

💡 Điểm khác biệt chính giữa quyền truy cập vào thẻ và quyền của máy chủ lưu trữ là gì?

Cả quyền "tabs" và quyền trên máy chủ lưu trữ đều có một số hạn chế.

Quyền "tabs" cấp cho một 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 vào thời gian cài đặt:

Hộp thoại cảnh báo quyền trên Thẻ

Quyền từ 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 một thẻ trùng khớp, đồng thời chèn tập lệnh trên các thẻ này. Người dùng sẽ thấy thông báo cảnh báo sau đây vào thời gian cài đặt:

Hộp thoại cảnh báo quyền của máy chủ

Những cảnh báo này có thể khiến người dùng lo lắng. Để có 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 thẻ

Bạn có thể truy xuất các thẻ từ 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 ngay trong cửa sổ bật lên không?

Các trang 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ập trung 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 chứa trong đó) theo thứ tự bảng chữ cái. Sau đó, khi một mục trong danh sách được nhấp, mục đó sẽ lấy tiêu điểm vào thẻ đó bằng cách sử dụng tabs.update() và đưa cửa sổ lên phía trước bằng cách sử dụ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 các mảng thẻ theo ngôn ngữ mà người dùng ưu tiên.
  • Thẻ mẫu dùng để xác định một phần tử HTML có thể sao chép được 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 trải rộng 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 nhóm tất cả các thẻ bằng cách sử dụng tabs.group() và di 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 tra để đả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ẻ: tệp manifest.json, cửa sổ bật lên.js, cửa sổ bật lên.css, cửa sổ bật lên.html và thư mục hình ảnh.

Tải tiện ích của bạn trên thiết bị

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

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

Mở các tài liệu sau đây 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 tiện ích Trình quản lý thẻ
Cửa sổ bật lên tiện ích Trình quản lý thẻ

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

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

🎯 Các điểm cải tiến có thể thực hiện

Dựa trên những điều bạn đã học hôm nay, hãy cố gắng triển khai bất kỳ cách nào sau đây:

  • Tuỳ chỉnh biểu định kiểu 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ẻ trên trang web tài liệu khác.
  • Thêm tính năng hỗ trợ việc 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 các kỹ năng của bạn bằng cách hoàn thành các bài hướng dẫn khác trong loạt hướng dẫn 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 thao tác với tiện ích.

Tiếp tục khám phá

Chúng tôi hy vọng bạn hài lòng với việc tạo tiện ích của Chrome này cũng như rất vui được tiếp tục hành trình tìm hiểu quá trình phát triển Chrome. Bạn nên tham gia lộ trình học tập sau đây:

  • Hướng dẫn dành cho nhà phát triển có hàng chục đường liên kết bổ sung đến các tài liệu liên quan đến việc tạo tiện ích nâng cao.
  • Các tiện ích có quyền truy cập vào những API mạnh mẽ ngoài những API có sẵn trên web mở. Tài liệu về API Chrome sẽ hướng dẫn từng bước về API.