谷歌插件的开发踩坑

340 阅读3分钟

先讲一下需求吧,业务方每天需要将同一个value 比如 123
根据对应的keyName 比如PlacementID 复制到对应的input标签内

这里有几百个input 所以需要 【重复操作】 且 【繁琐耗时】 所以就想开发一个插件 来解决这个痛点

image.png

首先先将谷歌插件的灵魂文件创建好

{
   "name": "广告来源表单插件",
   "version": "1.0",
   "description": "广告来源表单插件",
   "manifest_version": 2,
   "background": {
       "page": "js/background.js"
   },
   "content_scripts": [
       {
         "matches": [
           "<all_urls>"
         ],
         "js": [
           "js/jquery.min.js",
           "js/content.js"
         ],
         "css": [
           "css/content.css"
         ]
       }
     ],
   
   "permissions": [
     "declarativeContent",
     "storage",
     "activeTab",
     "tabs",
     "http://*/*"
   ],
   "page_action": {
       "default_popup": "html/popup.html",
 }
 }
 
  1. 坑一: 我无论左键还是右键点击插件的时候popup.html里我写的页面怎么不显示呢?

仔细查看发现是对谷歌的配置还是不太熟悉的关系 page_action指的是只有当某些特定页面打开才显示的图标,和browserAction最大的区别是一个始终都显示,一个只在特定情况才显示。

修改后的manifest.json文件
{
    "name": "广告来源表单插件",
    "version": "1.0",
    "description": "广告来源表单插件",
    "manifest_version": 2,
    "background": {
        "page": "js/background.js"
    },
    "content_scripts": [
        {
          "matches": [
            "<all_urls>"
          ],
          "js": [
            "js/jquery.min.js",
            "js/content.js"
          ],
          "css": [
            "css/content.css"
          ]
        }
      ],
    
    "permissions": [
      "declarativeContent",
      "storage",
      "activeTab",
      "tabs",
      "http://*/*"
    ],
    "browser_action": {
      "default_popup": "html/popup.html"
    }
  }
  1. 坑二:完善了popup页面写了一个按钮在按钮上绑定了对应的点击事件,审查发现事件并未执行,这又是为啥0.0?

image.png

翻阅资料发现

  1. 首先Chrome扩展程序不允许您使用内联JavaScript,所以你的js部分要写在一个外部的js文件中,一般叫做popup.js。
  2. 想要使click事件生效,我们需要监听在执行事件之前,页面已经加载完成
  3. 我这里因为需要和当前页面通信也就是【content.js】传递信息,我就这样写了
// popup.js
// 获取对应keyName 及 value
let btn = document.getElementById("syncBtn")
btn.onclick = function (e) {
    let keyName = document.getElementById("keyName").value;
    let value = document.getElementById("value").value;
    tabs(keyName, value);
}
// 去链接,对应的tab标签页面
async function tabs(...arg) {
    const tabId = await getCurrentTabId();
    console.log('tabId',tabId)
    const connect = chrome.tabs.connect(tabId, { name: 'popup' }); // 和指定tabID建立链接,并设置信号名字
    // 发送信息
    connect.postMessage(arg);
   
    // 接受返回信息
    connect.onMessage.addListener(mess => {
      console.log(mess)
    })
  };
  
// 获取当前 tab ID
function getCurrentTabId() {
    return new Promise((resolve, reject) => {
      chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        resolve(tabs.length ? tabs[0].id : null)
      });
    })
  };
 
 
// content.js

// 监听链接
chrome.runtime.onConnect.addListener(res => {
    if (res.name == "popup") {
      res.onMessage.addListener(mes => {
        console.log('🥓: popup.js receive', mes);
       });
    }

3.坑三:单纯的给input赋值了没用,页面内的校验逻辑无法通过,必须模拟人工真实输入的情形

这里我还试了先触发input的focus事件再去赋值都行不通,于是查了下如何触发input绑定的事件才得到了完美的解决,大佬原文 zhuanlan.zhihu.com/p/356661173

   // 获取label标签对应父元素的兄弟元素 input
            const element = $(v).parent().siblings()[0] //这里获取到了input
            var evt = new InputEvent('input', {
                inputType: 'insertText',
                data: value,
                dataTransfer: null,
                isComposing: false
            });
            element.value = value
            // 执行input上绑定的事件
            element.dispatchEvent(evt)

虽然一路上磕磕绊绊,但最终实现了功能,让业务方从1个小时重复复制粘贴变成了短短2分钟就能搞定的事情,心里还是蛮高兴的,以后希望大家遇到类似的需求能少走一些弯路。