從擴充功能存取網頁的`window`/DOM/HTML
P粉046878197
P粉046878197 2023-10-18 09:44:00
0
2
665

我正在編寫一個 Chrome 擴展程序,並嘗試在 popup.html 文件中單擊按鈕後立即在當前網頁上覆蓋

當我從 popup.html 存取 document.body.insertBefore 方法時,它會覆寫彈出視窗上的

,而不是目前網頁。

我是否必須在background.html 和popup.html 之間使用訊息傳遞才能存取網頁的DOM?我想在 popup.html 中完成所有操作,如果可能的話也使用 jQuery。

P粉046878197
P粉046878197

全部回覆(2)
P粉296080076

使用程式註入來新增該 div 的擴充彈出腳本的一些範例。

清單V3

不要忘記在manifest.json中新增權限,請參閱其他答案以獲取更多資訊。

  • 簡單呼叫:

    (async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      await chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: inContent1,
      });
    })();
    
    // executeScript runs this code inside the tab
    function inContent1() {
      const el = document.createElement('div');
      el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red';
      el.textContent = 'DIV';
      document.body.appendChild(el);
    }
    

    注意:在 Chrome 91 或更早版本中,func: 應為 function:

  • 使用參數呼叫並接收結果

    需要 Chrome 92,因為它實作了 args

    範例1:

    res = await chrome.scripting.executeScript({
      target: {tabId: tab.id},
      func: (a, b) => { return [window[a], window[b]]; },
      args: ['foo', 'bar'],
    });
    

    範例2:

    (async () => {
      const [tab] = await chrome.tabs.query({active: true, currentWindow: true});
      let res;
      try {
        res = await chrome.scripting.executeScript({
          target: {tabId: tab.id},
          func: inContent2,
          args: [{ foo: 'bar' }], // arguments must be JSON-serializable
        });
      } catch (e) {
        console.warn(e.message || e);
        return;
      }
      // res[0] contains results for the main page of the tab 
      document.body.textContent = JSON.stringify(res[0].result);
    })();
    
    // executeScript runs this code inside the tab
    function inContent2(params) {
      const el = document.createElement('div');
      el.style.cssText = 'position:fixed; top:0; left:0; right:0; background:red';
      el.textContent = params.foo;
      document.body.appendChild(el);
      return {
        success: true,
        html: document.body.innerHTML,
      };
    }
    

清單V2

  • 簡單呼叫:

    // uses inContent1 from ManifestV3 example above
    chrome.tabs.executeScript({ code: `(${ inContent1 })()` });
    
  • 使用參數呼叫並接收結果:

    // uses inContent2 from ManifestV3 example above
    chrome.tabs.executeScript({
      code: `(${ inContent2 })(${ JSON.stringify({ foo: 'bar' }) })`
    }, ([result] = []) => {
      if (!chrome.runtime.lastError) {
        console.log(result); // shown in devtools of the popup window
      }
    });
    

    此範例使用 inContent 函數的程式碼自動轉換為字串,這樣做的好處是 IDE 可以應用語法突出顯示和 linting。明顯的缺點是瀏覽器會浪費時間來解析程式碼,但通常不到 1 毫秒,因此可以忽略不計。

P粉600402085

問題:擴充頁面(彈出視窗、選項、MV2 中的背景頁面等)與網頁分離,它們有自己的DOM、document、window 和chrome-extension:// URL。

解決方案:使用內容腳本存取網頁頁面或與其內容互動。

  • 內容腳本在網頁中執行,而不是在擴充功能中執行。
  • 內容腳本預設是隔離的,請參閱如何在頁面上下文中執行程式碼(也稱為主世界)。
  • 不要在擴充功能頁面中載入內容腳本。

方法1.宣告式

manifest.json:

"content_scripts": [{
  "matches": ["*://*.example.com/*"],
  "js": ["contentScript.js"]
}],

它將在頁面載入時運行一次。之後,請使用訊息傳遞

警告!它不能傳送 DOM 元素、Map、Set、ArrayBuffer、類別、函數等。它只能發送與 JSON 相容的簡單物件和類型,因此您需要手動提取所需的資料並將其作為簡單陣列或物件傳遞。

方法 2. 程式化

  • ManifestV3

    在擴充腳本(如彈出視窗)可根據需要將內容腳本/函數注入標籤。

    此方法的結果是內容腳本中的最後一個表達式,因此可用於擷取資料。資料必須與 JSON 相容,請參閱上面的警告。

    manifest.json 中所需的權限

    • 「腳本」 - 強制;
    • "activeTab" - 理想場景,適合對使用者操作的回應(通常是點擊工具列中的擴充圖示)。安裝擴充功能時不顯示任何權限警告。

    如果理想情況不可能,請將允許的網站新增至manifest.json 中的host_permissions

    • 「*://*.example.com/」 以及您想要的任何其他網站。

    • """*://*/" 這些會將您的擴充功能置於Chrome 線上應用程式商店中超慢審核佇列中由於廣泛的主機權限。

  • ManifestV2 與上述的差異:

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板