一个动态获取网页元素数据的chrome插件

2,088 阅读2分钟

1、为啥

最近写的bug有点多

禅道上给我提的bug,只有刷新之后才会知道有几个

可能有时候沉浸式开发,突然想起来禅道,一刷新好多bug。。。。

2、所以

想整个插件

定时刷新禅道页面 获取bug数量 提示出来

3、整

chrome开发者文档地址 developer.chrome.com/docs/extens…

  • 1、配置文件

manifest.json 在配置文件里处理好 全局文件 单独页面文件 权限

  • 全局文件 service_worker

  • 单页面文件 content_scripts (就是注入到哪个页面里)

  • 权限 permissions

  • 插件弹出的页面 default_popup

{
  "name": "禅",
  "description": "chrome 插件",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": [
    "storage",
    "tabs"
  ],
  "action": {
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["http://172.16.175.90:18080/zentao/my/"],
      "js": ["zentao.js"]
    }
  ]
}
  • 2、先处理全局文件

思路:

  1. 先看禅道页面是否在打开
  2. 如果在打开 获取 tabid 进行页面处理
  3. 没打开就 先新建tab 在进行2
  4. 处理定时器 轮询
  5. 刷新tab 后告诉 单页面文件
  6. 单页面文件 获取到数据 在发回来
  7. 展示
const pageUrl = "http://172.16.175.90:18080/zentao/my/";
let isQuery = false;
let tabId = "";

async function createTab() {
  const tab = await chrome.tabs.create({
    index: 0,
    url: pageUrl,
    active: true,
  });
  console.log("创建", tab);
  return tab;
}

async function getTabId() {
  if (isQuery && tabId) return tabId;
  const tabs = await chrome.tabs.query({ url: pageUrl });
  if (tabs.length) {
    // if (tabs.length > 1) {
    //   const removeIds = tabs.map((v) => v.id).filter((_, i) => i > 0);
    //   chrome.tabs.remove(removeIds);
    // }
    const tab = await chrome.tabs.update(tabs[0].id, { active: true });
    tabId = tab.id;
    isQuery = true;
    return tab.id;
  } else {
    const tab = await createTab();
    tabId = tab.id;
    isQuery = true;
    return tab.id;
  }
}

chrome.runtime.onMessage.addListener(async (msg, sender) => {
  if (msg.type === "setText") {
    chrome.action.setBadgeText({
      text: msg.text || "",
    });
    chrome.action.setBadgeBackgroundColor({
      color: "#f45",
    });
  } else if (msg.type === "reload") {
    timeoutQueryPageText();
  } else if (msg.type === "close") {
    console.log("结束", timeId);
    clearTimeout(timeId);
  }
});

chrome.storage.sync.set({ isStart: false });

let timeId = "";
let a = 1;
async function timeoutQueryPageText() {
  const tabId = await getTabId();
  console.log("轮询", tabId);
  timeId && clearTimeout(timeId);
  timeId = setTimeout(() => {
    console.log("刷新次数", a++);
    chrome.tabs.reload(tabId, { bypassCache: false }, () => {
      chrome.tabs.sendMessage(tabId, { type: "reloadEnd" });
    });
  }, 60000);
  console.log("timeId", timeId);
}

  • chrome.tabs.sendMessage(tabId, { type: "reloadEnd" }); 全局文件可以通过tabs 的sendMessage 给单独的页面文件发消息
  • chrome.runtime.onMessage.addListener 监听消息 所有消息都会监听到

单页面文件 是注入到 页面内的 处理不了插件设置

  • chrome.action.setBadgeBackgroundColor 处理插件徽标的背景色

  • chrome.action.setBadgeText 处理插件徽标的背景色

  • 3、插件弹出页面处理

我这个做的简单 html里只做了个按钮(开始 结束)

开始 就执行轮询 定时刷新 结束 清除定时器

const btn = document.querySelector("#show");
btn.addEventListener("click", async () => {
  const { isStart } = await chrome.storage.sync.get(["isStart"]);
  if (isStart) {
    // 关闭
    console.log("关闭");
    chrome.runtime.sendMessage({ type: "close" });
    await chrome.storage.sync.set({ isStart: !isStart });
  } else {
    // 开启
    console.log("开始");
    chrome.runtime.sendMessage({ type: "reload" });
    await chrome.storage.sync.set({ isStart: !isStart });
  }
  setButtonText();
});

function setButtonText() {
  chrome.storage.sync.get(["isStart"], function (v) {
    btn.innerHTML = !v.isStart ? "开始监听" : "关闭监听";
    if (!v.isStart) {
      chrome.runtime.sendMessage({ type: "setText", text: "" });
    }
  });
}
setButtonText();
  • chrome.storage.sync 获取设置存储的方法

  • chrome.runtime.sendMessage 发送消息的方法(全局 单页面 弹出 这几个文件之间的通讯就靠这个)

  • 4、处理单页面文件

这个文件是注入到页面内的,所以可以操作获取页面元素等等各种操作。

// 刷新完成
chrome.runtime.onMessage.addListener(async (msg, sender) => {
  if (msg.type === 'reloadEnd') {
    const textDomList = frames[0].document.querySelectorAll(".tile-amount");
    const textList = [...textDomList][1];
    const text = textList.innerHTML;
    console.log("开始执行 --- dom", text);
    chrome.runtime.sendMessage({ type: "setText", text: '' + Math.round(Math.random() * 100) });
    chrome.runtime.sendMessage({ type: "reload"});
  }
})

这步就是等 全局文件刷新 tab 完成后获取 元素数据 在发送给全局文件。

4、又不是不能用

可以把 plug 文件夹 拽到 扩展程序里 得改一改配置文件啥的

github github.com/dongdaxin/z…