- 在單擊此 iframe 中
<iframe>的 a 后,我需要在 a 中注入一個元素。<button> - 這
<iframe>存在于不受我控制的頁面(例如 somewebpage.com)中。 - 的
<iframe>內容與主檔案的正文/DOM 結構屬于同一域。 - 為此,我需要根據以下 V3 清單的
"content_scripts"配置使用來自 Chrome 擴展的內容腳本檔案:
"content_scripts": [
{
"type": "module", // I added this items "type", "run_at", "all_frames"
"run_at": "document_end", // and "match_origin_as_fallback" hoping they
"all_frames": true, // would help.
"match_origin_as_fallback": true,
"js": [
"foreground.js" // File containing the pure JS code
],
"matches": [
"https://somewebpage.com/*" // The page where I want to inject the element
]
擴展的內容腳本"foreground.js"檔案包含應該檢測 iframe、監聽click事件并在click檢測到后將元素注入 iframe 中的代碼。
頁面完全加載后,當我檢查這個頁面上的元素時,它基本上是這樣的:
<body>
<macroponent>
#shadow-root (open) <!-- Shadow DOM element. I believe this is what is my main obstacle -->
<div>
<sn-canvas-appshell-root>
<sn-canvas-appshell-layout>
<sn-polaris-layout>
<iframe id="myIframe"> <!-- to access button I need to find the iframe 1st -->
<button id="myButton">TAKE</button> <!-- I need to get that click event -->
</iframe>
</sn-polaris-layout>
</sn-canvas-appshell-root>
</sn-canvas-appshell-root>
</div>
</macroponent>
</body>
我嘗試了很多不同的方法,但沒有一個能夠找到<iframe>. 控制臺上的錯誤訊息回傳getElementByIdasnull和getElementsByTagNameas undefined。
作為一種標準方法,我嘗試了一些變化,例如window.onload:
document.onreadystatechange = () => {
if (document.readyState === 'complete') {
let iframe = document.getElementsByTagName('iframe')[0];
iframe.contentDocument.getElementById("myButton").addEventListener("click", function () {
alert("Hurray!");
// Injected element code here
});
}
我還嘗試了一些更高級的解決方案,例如:
function searchFrame(id) { // id = the id of the wanted (i)frame
var result = null, // Stores the result
search = function (iframes) { // Recursively called function
var n; // General loop counter
for (n = 0; n < iframes.length; n ) { // Iterate through all passed windows in (i)frames
if (iframes[n].frameElement.id === id) { // Check the id of the (i)frame
result = iframes[n]; // If found the wanted id, store the window to result
}
if (!result && iframes[n].frames.length > 0) { // Check if result not found and current window has (i)frames
search(iframes[n].frames); // Call search again, pass the windows in current window
}
}
};
search(window.top.frames); // Start searching from the topmost window
return result; // Returns the wanted window if found, null otherwise
}
來源:
獲取嵌套在 JavaScript 框架內的 iframe 內的元素值?
在我看來,這個問題仍然存在,可能是因為它<iframe>是“Shadow DOM”元素的子元素,這使得查找方法<iframe>與標準不同。
在意識到問題可能是“Shadow DOM”<iframe>元素的子 元素之后,我從另一個問題嘗試了這種方法:
this.windows = this.shadowRoot.getElementsByTagName('app-window')
來源:
Shadow DOM 中的 GetElementById
甚至是這個:(
盡管我懷疑這對我的用例來說可能有點矯枉過正)
customElements.define("my-component", class extends HTMLElement {
constructor() {
super().attachShadow({mode:"open"}).innerHTML = `<slot></slot>`;
}
})
const shadowDive = (
el,
selector,
match = (el, root) => {
console.warn('match', el, root);
},
root = el.shadowRoot || el
) => {
root.querySelector(selector) && match(root.querySelector(selector), root);
[...root.querySelectorAll("*")].map(el => shadowDive(el, selector, match));
}
shadowDive(document.body, "content"); // note optional parameters
來源:
如何從影子根中選擇元素標簽
我再次得到相同null或undefined錯誤。但我認為,既然我知道<iframe>嵌套在“Shadow DOM”元素中,我可能走在正確的軌道上。
也許有一種方法可以繞過或尊重“Shadow DOM”并做到這一點,<iframe>但老實說我沒有想法。
謝謝
uj5u.com熱心網友回復:
- shadowRoot 沒有
getElementsByTagName. - ShadowDOM 框架未在全域中公開
window或frames(順便說一句,這是同一件事) - customElements.define 在內容腳本中不起作用(由于“世界隔離”)。
您可以使用 querySelector contentDocument:
const el = document.querySelector('macroponent').shadowRoot.querySelector('iframe');
const elInner = el.contentDocument.querySelector('div');
請注意,您不需要all_framesor match_origin_as_fallback,因為 iframe 是同源的,因此可以從主檔案的內容腳本直接訪問它,如上所示。
一個陷阱是現代網站動態生成頁面內容,通常取決于網路回應,這可能會在您的所有內容腳本運行很長時間后發生。在這種情況下,您可以使用 MutationObserver 來檢測它,或者只是在 setInterval 中定期重新檢查。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/524320.html
