Javascript 如何从扩展中检测Google Chrome中的页面标题更改?
我正在创建一个Google Chrome扩展,我需要检测页面标题何时更改。页面标题的更改与Twitter中的更改类似:Javascript 如何从扩展中检测Google Chrome中的页面标题更改?,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在创建一个Google Chrome扩展,我需要检测页面标题何时更改。页面标题的更改与Twitter中的更改类似:(num)Twitter(请参见下面的屏幕截图)-当发布新的tweet时,数量会增加。例如: 我正在尝试检测加载到我的一个选项卡中的URL的标题更改,并在出现差异时播放嘟嘟声。此检查需要重复进行,我认为可以使用setTimeOut()函数来完成 我创建了一个manifest.json,如下所示: { "manifest_version": 2, "name": "De
(num)Twitter
(请参见下面的屏幕截图)-当发布新的tweet时,数量会增加。例如:
我正在尝试检测加载到我的一个选项卡中的URL的标题更改,并在出现差异时播放嘟嘟声。此检查需要重复进行,我认为可以使用setTimeOut()
函数来完成
我创建了一个manifest.json
,如下所示:
{
"manifest_version": 2,
"name": "Detect Page Title Changes",
"description": "Blah",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "background.html"
},
"permissions": [
"tabs"
]
}
然而,我对其余的一无所知。我已经搜索了文档,并在类似的堆栈溢出线程(如我)上尝试了解决方案,但没有找到任何适合我的要求的解决方案
你有什么建议吗?如果可能,请附上一个例子
window.document.title
是否更改在研究了Chrome的tabs API之后,它看起来并没有什么可以直接帮助您的。但是,您应该能够将事件侦听器附加到您感兴趣的选项卡的标题节点。DOMSubtreeModified突变事件在Chrome中起作用,在普通html文档中进行快速测试证明对我有效——应该与在扩展中没有什么不同
var title = document.getElementsByTagName('title')[0];
if (title) {
title.addEventListener('DOMSubtreeModified', function (e) {
// title changed
}, false);
}
与其在评论中争论某种方法更好,不如让我更具建设性,通过展示我自己写的一篇文章来补充答案,并解释一些你可能遇到的问题代码片段指的是与Twitter不同的服务,但目标是相同的。事实上,此代码的目标是报告未读邮件的确切数量,因此您的代码可能更简单 我的方法基于此,而不是轮询驱动(按固定时间间隔检查条件),而是事件驱动(通知条件的潜在变化) 优点包括立即检测到更改(否则在下次轮询之前不会检测到更改),并且在条件不变时不会在轮询上浪费资源。诚然,第二种观点在这里几乎不适用,但第一种观点仍然有效
架构概览:
sendMessage
向后台页面报告sendMessage
向后台页面报告步骤1已经有了一个解决方案。当在清单中定义内容脚本时,正常的内容脚本注入机制将在导航到与URL匹配的页面时将其注入页面
"content_scripts": [
{
"matches": [
"*://theoldreader.com/*"
],
"js": ["observer.js"],
"run_at": "document_idle"
}
]
在重新加载扩展之前,这工作得很好。这可能发生在应用所做更改的开发中,也可能发生在自动更新的已部署实例中。然后,内容脚本不会重新注入现有的打开页面(直到导航发生,就像重新加载一样)。因此,如果依赖于基于清单的注入,当扩展初始化时,还应该考虑包括编程注入已打开的选项卡:
function startupInject() {
chrome.tabs.query(
{url: "*://theoldreader.com/*"},
function (tabs) {
for (var i in tabs) {
chrome.tabs.executeScript(tabs[i].id, {file: "observer.js"});
}
}
);
}
另一方面,在扩展重新加载时处于活动状态的内容脚本实例不会终止,而是孤立的:任何发送消息
或类似请求都将失败。因此,建议在尝试与父扩展通信时始终检查异常,并在失败时自行终止(通过删除处理程序):
try {
chrome.runtime.sendMessage({'count' : count});
} catch(e) { // Happens when parent extension is no longer available or was reloaded
console.warn("Could not communicate with parent extension, deregistering observer");
observer.disconnect();
}
第二步也有一个解决办法,尽管这取决于你正在观看的服务的具体情况。内容脚本范围内的某些页面不会显示未读项目的数量,但这并不意味着没有新消息 在观察了web服务的工作方式之后,我得出结论,如果标题更改为没有导航的内容,则可以安全地假设新值(如果正确),但对于初始标题,“无新项目”应被忽略,因为它不可靠 因此,分析代码说明是初始读取还是处理更新:
function notify(title, changed) {
// ...
var match = /^\((\d+)\)/.exec(title);
var match_zero = /^The Old Reader$/.exec(title);
if (match && match[1]) {
count = match[1];
} else if (match_zero && changed) {
count = 0;
}
// else, consider that we don't know the count
//...
}
在第2步中,使用初始标题和changed
=false
调用它
步骤3和步骤4是“如何观察标题更改”(以事件驱动的方式)的主要答案。
var target = document.querySelector('head > title');
var observer = new window.MutationObserver(
function(mutations) {
mutations.forEach(
function(mutation){
notify(mutation.target.textContent, true);
}
);
}
);
observer.observe(target, { subtree: true, characterData: true, childList: true });
有关设置observer.observe
某些选项的具体原因,请参阅
请注意,
notify
是使用changed
=true
调用的,因此从“(1)旧阅读器”到“旧阅读器”而不进行导航被视为“真”更改为零未读消息。在后台脚本中放置chrome.tabs.onUpdated.addListener
:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
console.log(changeInfo);
});
changeInfo
是一个包含标题更改的对象,例如:
然后可以对对象进行筛选,以便仅当
changeInfo
包含标题更改时才会发生操作。对于其他操作,例如使用页面内容/操作响应页面标题的更改,您可以在满足任何条件后从侦听器内部向内容脚本发送消息。如果您正在轮询,是否需要事件?你不能只存储最后一个标签标题并将其与当前标签标题进行比较吗?我认为使用事件(如果有)是一个好主意。但是如果没有,你的想法可以是你