我有一个书签,我正在迁移到Chrome扩展程序。这是一个Angular应用程序。目前,它使用browser action和background script来允许用户调用应用程序注入页面。
一旦注入页面,扩展程序应允许用户再次单击浏览器操作以切换界面的可见性。目前,多次单击浏览器操作会看到后台脚本尝试将所有JavaScript文件重新注入页面,抛出如下错误:
警告:尝试多次加载角度
如何在后台脚本中保留一些状态,允许切换注入的接口,而不必每次都执行扩展的初始化?
答案 0 :(得分:0)
在我们陷入困境之前,我们需要配置Chrome扩展程序,使其具有......
activeTab
,web_accessible_resources
(脚本和样式表)列表,webNavigation
个事件,以便我们知道用户何时刷新或在标签中导航,background.scripts
下定义的后台脚本。让我们看看实际的manifest.json
文件*:
// manifest.json
"background": {
"scripts": ["background.js"]
},
"web_accessible_resources": [
"angular.min.js",
"jquery.min.js",
"main.js",
"style.css"
],
"permissions": [
"activeTab",
"webNavigation",
"http://*/*"
]
*部分manifest.json显示
______
通过维护id
主题及其主题的哈希,可以在单个选项卡的生命周期内维护状态(例如,单击浏览器操作),类似于在其他情况下维护状态的方式会话数据。在这种情况下,主题是选项卡。我们可以从浏览器操作的点击处理程序中访问标签id
。例如:
// background.js
var clicked = {};
chrome.browserAction.onClicked.addListener(function (tab) {
clicked[tab.id] = (clicked[tab.id] || 0) + 1;
});
选项卡的状态将持续导航到其他网页,因此我们还需要监听一个事件,告诉我们导航已经发生,这意味着页面中不再存在扩展名,并重置选项卡的状态:
// background.js continued
// Reset state of our tab data when the page is refreshed
chrome.webNavigation.onDOMContentLoaded.addListener(function (details) {
clicked[details.tabId] = 0;
});
______
background.js
)使用上面的示例,我们可以通过存储一个布尔值来执行脚本的条件注入,该布尔值指示扩展是否已在活动选项卡上初始化。在初始化时,我们希望注入所需的所有脚本,并且在后续的操作调用中只注入我们自己的客户端脚本 - 假设我们有一个文件main.js
构成扩展自己的有效负载(它不是包含应该只注入一次的供应商脚本:
// background.js
var initialised = {};
chrome.webNavigation.onDOMContentLoaded.addListener(function (details) {
initialised[details.tabId] = false;
});
chrome.browserAction.onClicked.addListener(function (tab) {
// When extension already exists in page, load
// a script that will toggle the interface
if (initialised[tab.id]) {
chrome.tabs.executeScript(tab.id, {file: 'main.js'});
return;
}
// Mark this tab as 'initialised'
initialised[tab.id] = true;
var javascripts = [
"jquery.min.js",
"angular.min.js",
"main.js"
];
var stylesheets = [
"style.css"
];
var i;
for (i = 0; i < javascripts.length; i++) {
chrome.tabs.executeScript(tab.id, {file: javascripts[i]});
}
for (i = 0; i < stylesheets.length; i++) {
chrome.tabs.insertCSS(tab.id, {file: stylesheets[i]});
}
});
______
main.js
)注射完成后,我们将处于以下两个位置之一:
初始化扩展应该通过声明模块并插入所有模板等来完成(如果扩展完全是自定义的,则执行初始化,但是你觉得合适。)
因此,我们的main.js
文件应执行以下操作:
_my_chrome_extension
),表示页面中已存在扩展名。isVisible
(或类似)。isVisible = !isVisible
)的反面。run
块或类似内容中),将属性isVisible
设置为true,以便界面自动显示。代码示例......
// main.js
(function (angular, $) {
var scope;
// Check if application exists in page already
if (typeof window['_my_chrome_extension'] !== 'undefined') {
var elem = document.querySelector('._extension_container');
scope = angular.element(elem).scope();
}
if (scope) {
// TOGGLE VISIBILITY
scope.isVisible = !scope.isVisible;
scope.$applyAsync();
} else {
window['_my_chrome_extension'] = true;
// PERFORM INITIALISATION
// ANGULAR APP GOES HERE
}
})(angular, jQuery);
快速地说,在您的模板中,您将需要类似以下的内容,根据isVisible
的值显示/隐藏界面:
// template.html
<div id="_my_chrome_extension" ng-show="isVisible"></div>