提问人:Verminous 提问时间:10/28/2022 更新时间:10/28/2022 访问量:2491
如何捕获嵌套在 Shadow DOM 的“#shadow 根(开放)”元素中的 iframe?
How to capture iframe nested within Shadow DOM's "#shadow-root (open)" element?
问:
- 我需要在 中注入一个元素,然后单击此 iframe 中的 。
<iframe>
<button>
- 这存在于不受我控制的页面(例如 somewebpage.com)中。
<iframe>
- 的内容与主文档的正文/DOM 结构属于同一域。
<iframe>
- 为此,我需要根据以下 V3 清单的配置使用 Chrome 扩展程序中的内容脚本文件:
"content_scripts"
"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
]
扩展的内容脚本文件包含的代码应检测 iframe,侦听事件,然后在检测到 iframe 后将元素注入 iframe。"foreground.js"
click
click
页面完全加载后,当我检查这个页面上的元素时,它基本上看起来像这样:
<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>
我尝试了很多不同的方法,但没有一个能够找到.控制台上的错误消息返回 as 和 as 。<iframe>
getElementById
null
getElementsByTagName
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 中获取嵌套在 Frame 中的 iframe 中的元素值?
在我看来,这个问题仍然存在,可能是因为它是“影子 DOM”元素的子元素,这使得查找方法与标准不同。<iframe>
<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
我再次得到相同或错误。
但我认为,也许我现在走在正确的轨道上,因为我知道它嵌套在“Shadow DOM”元素中。null
undefined
<iframe>
也许有一种方法可以绕过或尊重“影子 DOM”并实现这一目标,但老实说,我没有想法。<iframe>
谢谢
答:
- shadowRoot 没有 .
getElementsByTagName
- ShadowDOM 帧不会在全局或(顺便说一句,这是一回事)
window
frames
- customElements.define 在内容脚本中不起作用(由于“世界隔离”)。
你可以使用 querySelector + contentDocument:
const el = document.querySelector('macroponent').shadowRoot.querySelector('iframe');
const elInner = el.contentDocument.querySelector('div');
请注意,您不需要 or 此处,因为 iframe 是同源的,因此可以从主文档的内容脚本直接访问它,如上所示。all_frames
match_origin_as_fallback
一个陷阱是,新式网站会动态生成页面内容,这通常取决于网络响应,这可能会在所有内容脚本运行后很长时间内发生。在这种情况下,您可以使用 MutationObserver 来检测它,或者只是在 setInterval 中定期重新检查。
评论
el.contentDocument.getElementById("myButton").addEventListener("click", funtion() {...
评论