我正在编写一个Google Chrome扩展程序,我在其中解析所加载的任何页面的<head>
标记,并查找特定的<meta>
标记。内容脚本用于与站点通信,然后在后台脚本中完成实际逻辑。
问题是后台脚本应该要求内容脚本检查<meta>
标记。 chrome.webNavigation.onDOMContentLoaded
似乎是安全的,但我发现通常在加载页面时会多次触发此事件。此外,<head>
可能在chrome.webNavigation.onDOMContentLoaded
点击之前可用。这一切都让我想到了这个问题:
如何最好地检查页面的<head>
部分何时加载?
答案 0 :(得分:0)
由于您无论如何都要将内容脚本注入所有页面,因此可以在其中完成任务,而不是总是等待页面完全加载(可能需要很长时间,具体取决于连接速度和其他因素)
在文档加载开始时注入内容脚本,并使用document.head
附加的MutationObserver在页面加载过程中立即获取结果,因为它已插入DOM 。观察者只会看到HEAD
元素的直接子元素,因此不会影响性能。
某些网站可能会在加载页面后添加meta
个元素 - 这将被观察者捕获。
的manifest.json:
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_start"
}],
content.js:
如果存在HEAD
,请查找所需的meta
元素,否则请等待HEAD
插入。
if (document.head) {
examineHead();
} else {
new MutationObserver(function(mutations) {
if (document.head) {
this.disconnect();
examineHead();
}
}).observe(document.documentElement, {childList: true});
}
function examineHead() {
var nodes = document.head.getElementsByTagName('meta');
for (var i = 0; i < nodes.length; i++) {
var n = nodes[i];
if (reportMetaNode(n)) {
return;
}
}
observeHead();
}
观察document.head
并检查每个新元素是否属于那个元素。
function observeHead() {
new MutationObserver(function(mutations) {
for (var i = 0; i < mutations.length; i++) {
var nodes = mutations[i].addedNodes;
for (var j = 0; j < nodes.length; j++) {
var n = nodes[j];
if (n.localName == 'meta') {
if (reportMetaNode(n)) {
this.disconnect();
return;
}
}
}
}
}).observe(document.head, {childList: true});
}
例如,让我们查找<meta name="twitter:app:id:googleplay" content="......">
并向后台脚本发送一条消息,其值为content
。
function reportMetaNode(n) {
console.log(n, n.outerHTML);
if (n.name == "twitter:app:id:googleplay") {
chrome.runtime.sendMessage({gotMeta: n.content});
return true;
}
return false;
}
您可能还希望处理其他类型的突变,例如characterData
和attributes
,因为某些网站可能会在单独的步骤中更改或添加元素(createElement,setAttribute,附加子文本节点等等) ),在这种情况下,观察者回调会更复杂,subtree: true
参数中需要observe()
。