# 使用 Plasmo 设置浏览器插件动态 Icon

## 背景

最近在开发浏览器插件`免登录一键复制 (codebox-浏览器插件)`时，想动态设置图标可以提升用户体验。本文将介绍如何使用 `Plasmo` 框架实现这一功能。

## 前提条件

1. 安装 `Plasmo`：确保你已经安装了 `Plasmo` 框架。如果没有，请参考 `Plasmo` 官方文档 进行安装。
2. 基础知识：了解基本的 `JavaScript` 和浏览器插件开发。

### 步骤一：创建 `Plasmo` 项目

首先，创建一个新的 `Plasmo` 项目：

```ssh
    npx plasmo init my-extension
    cd my-extension
```

### 步骤二：安装 `Messaging` 依赖

然后，安装 `Plasmo` 的 `Messaging` 依赖：

```ssh
pnpm install @plasmohq/messaging
```

### 步骤三：配置 `manifest.json`
`Plasmo` 会自动生成 `manifest.json` 文件，但我们需要手动添加 `action` 字段来支持动态图标：

```json
{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  "action": {
    "default_icon": {
      "16": "icons/icon16.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "background": {
    "service_worker": "background.js"
  }
}
```
### 步骤四：创建背景文件夹和文件
该 `@plasmohq/messaging` 库要求后台服务工作者位于 `background/index.ts `文件夹内，并且所有消息处理程序都位于`background/*`文件夹内。

如果您已经有`background.ts`或`background.js`文件，则必须创建一个`background`文件夹并将您的脚本移动到`background/index.ts`或`background/index.js`。

如果您还没有`background`文件夹，请创建一个`background`文件夹并创建一个新的、空的`background/index.ts`或`background/index.js`文件。

现在，您将能够在`background/`子文件夹中创建新的处理程序。例如，要创建`messages`名为 的处理程序`ping`，您需要创建`background/messages/ping.ts`。

此时，您的文件夹结构可能看起来像这样。

```
.
├── background
│   ├── index.ts
│   └── messages
│       ├── tab.ts
│       └── icon.ts
```

### 步骤五：编写背景脚本

在 `background/icon.ts` 中，使用 `chrome.action.setIcon` 动态设置图标：

```tsx
import defaultUrl from "raw:~/assets/icon.png"
import activeUrl from "raw:~/assets/logo.png"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
  const [tab] = await chrome.tabs.query({ currentWindow: true, active: true })
  const { active } = req.body

  if (active) {
    chrome.action.setIcon({ tabId: tab.id, path: activeUrl }, () => {
      console.log("set icon activeUrl")
    })
  } else {
    chrome.action.setIcon({ tabId: tab.id, path: defaultUrl }, () => {
      console.log("set icon defaultUrl")
    })
  }
}

export default handler
```

### 步骤六：发送消息更改图标
在你的插件中，通过发送消息来更改图标。例如，在 `popup.js` 中：

```js
import { sendToBackground } from "@plasmohq/messaging"

export function setIcon(active: boolean) {
  sendToBackground({
    name: "icon",
    body: {
      active: active
    }
  })
}
```

### 步骤七：测试插件

1. 加载插件：在浏览器中打开 `chrome://extensions/`，启用开发者模式，加载已解压的扩展程序。
2. 测试功能：点击按钮，验证图标是否动态更改。

## 结论

通过上述步骤，你可以使用 `Plasmo` 框架轻松实现浏览器插件的动态图标设置。这不仅提升了用户体验，还展示了 `Plasmo` 的强大功能。

希望这篇文章对你有所帮助！

>因为这款插件的源代码是开源的，完整代码大家可以直接看我的 Github 仓库：
>
> https://github.com/027xiguapi/code-box
>

本浏览器插件可以用于`CSDN/知乎/脚本之家/博客园/博客园/51CTO博客/php中文网`等网站，实现无需登录一键复制代码;支持选中代码;或者代码右上角按钮的一键复制;解除关注博主即可阅读全文提示;去除登录弹窗;去除跳转APP弹窗。功能上已经可以满足要求。可能还有很多不足的地方，大家发现了问题或者有其他需求的话，欢迎向我反馈。


## 参考

[【plasmo Messaging API】](https://docs.plasmo.com/framework/messaging)