切换页内Angular Chrome扩展程序的可见性

时间:2015-10-21 13:09:14

标签: javascript angularjs google-chrome-extension

我有一个书签,我正在迁移到Chrome扩展程序。这是一个Angular应用程序。目前,它使用browser actionbackground script来允许用户调用应用程序注入页面。

一旦注入页面,扩展程序应允许用户再次单击浏览器操作以切换界面的可见性。目前,多次单击浏览器操作会看到后台脚本尝试将所有JavaScript文件重新注入页面,抛出如下错误:

  

警告:尝试多次加载角度

如何在后台脚本中保留一些状态,允许切换注入的接口,而不必每次都执行扩展的初始化?

1 个答案:

答案 0 :(得分:0)

清单

在我们陷入困境之前,我们需要配置Chrome扩展程序,使其具有......

  1. 使用权限activeTab
  2. 访问有效标签
  3. 扩展程序将注入的web_accessible_resources(脚本和样式表)列表,
  4. 访问webNavigation个事件,以便我们知道用户何时刷新或在标签中导航,
  5. 和在属性background.scripts下定义的后台脚本。
  6. 让我们看看实际的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

    切换或初始化扩展

    注射完成后,我们将处于以下两个位置之一:

    1. 扩展需要完全初始化,因为这是用户第一次在活动选项卡上调用它。 (在这种情况下,将注入所有供应商文件客户端脚本。
    2. 应该在视图中切换扩展名。 (在这种情况下,只会注入客户端脚本。
    3. 初始化扩展应该通过声明模块并插入所有模板等来完成(如果扩展完全是自定义的,则执行初始化,但是你觉得合适。)

      因此,我们的main.js文件应执行以下操作:

      1. 查找全局标记(例如_my_chrome_extension),表示页面中已存在扩展名。
      2. 如果标志存在:
        1. 获取Angular应用程序的范围并检索属性isVisible(或类似)。
        2. 将标志设置为其当前值(isVisible = !isVisible)的反面。
      3. 如果该标志不存在:
        1. 引导Angular应用程序。
        2. 在Angular应用中(例如在run块或类似内容中),将属性isVisible设置为true,以便界面自动显示。
      4. 代码示例......

        // 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>