gpt4 book ai didi

javascript - 在已经使用 Angular 的页面上的扩展中使用 Angular

转载 作者:可可西里 更新时间:2023-11-01 01:17:24 24 4
gpt4 key购买 nike

我正在为 here 编写一个 Chrome 扩展程序( my library )对 its UI 使用 angular .它在不使用 Angular 页面上效果很好,但它会导致具 Angular 页面出现问题。例如,在 Angular 文档页面上:

Uncaught Error: [$injector:modulerr] Failed to instantiate module docsApp due to:
Error: [$injector:nomod] Module 'docsApp' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.2.7/$injector/nomod?p0=docsApp
at chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:78:14
at chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:1528:19
at ensure (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:1453:40)
at module (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:1526:16)
at chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:3616:24
at Array.forEach (native)
at forEach (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:302:13)
at loadModules (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:3610:7)
at createInjector (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:3550:13)
at doBootstrap (chrome-extension://cfgbockhpgdlmcdlcbfmflckllmdiljo/angular.js:1298:22)
http://errors.angularjs.org/1.2.7/$injector/modulerr?p0=docsApp&p1=Error%3A…xtension%3A%2F%2Fcfgbockhpgdlmcdlcbfmflckllmdiljo%2Fangular.js%3A1298%3A22) angular.js:78

奇怪的是,无论我的扩​​展是否真的使用 angular 似乎都会发生。重现该问题所需要做的就是将 angular 作为 content_script 包含在我的 manifest.json 中,然后抛出此错误。任何关于如何在不弄乱 Angular 站点的情况下完成这项工作的想法将不胜感激。

就像我说的,我是否真的使用 angular 并不重要,但这就是我使用它所做的一切:

makeWishForAnchors(); // This just loads the global genie object. I don't believe it's related.

var lamp = '<div class="genie-extension"><div ux-lamp lamp-visible="genieVisible" rub-class="visible" local-storage="true"></div></div>';
$('body').append(lamp);

angular.module('genie-extension', ['uxGenie']);
angular.bootstrap($('.genie-extension')[0], ['genie-extension']);

谢谢!

最佳答案

问题

一旦 Angular 被注入(inject),它就会解析 DOM 以寻找带有 ng-app 的元素。指示。如果找到一个,Angular 将自动引导。当页面使用 Angular 本身时,这会成为一个问题,因为(尽管它们具有独立的 JS 执行上下文)页面和内容脚本共享相同的 DOM。

解决方案

您需要防止您的 Angular 实例(“您的”我指的是您的扩展作为内容脚本注入(inject)的实例)自动引导。通常你会忽略 ng-app指令,你会很高兴去,但由于你无法控制原始 DOM(也不想破坏页面的功能),这不是一个选项。

可以做什么使用 manual bootstrapping deferred bootstrapping 一起用于您的 Angular 应用程序(以防止您的 Angular 尝试自动引导页面的 Angular 应用程序)。

同时,您需要从页面的 Angular 实例中“保护”(即隐藏)您应用的根元素。为此,您可以使用 ngNonBindable 将根元素包裹在父元素中。 指令,因此页面的 Angular 实例将不理会它。

总结上述文档中的步骤,您需要执行以下操作:

  1. 前置 window.nameNG_DEFER_BOOTSTRAP!在注入(inject) Angular 之前。
    例如。注入(inject)一个只包含一行的小脚本(在 angluar.js 之前):

    window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
  2. 将应用的根元素包装在具有属性 ng-non-bindable 的父元素中:

    var wrapper = ...    // <div ng-non-bindable></div>
    wrapper.appendChild(lamp); // or whatever your root element is
    document.body.appendChild(wrapper);
  3. 在您应用的主脚本中,手动引导您的 Angular 应用:

    var appRoot = document.querySelector('#<yourRootElemID');
    angular.bootstrap(appRoot, ['genie-extension']);

<罢工><子>细则:我自己还没有测试过,但我保证会尽快测试!


更新

下面的代码旨在证明上述方法的概念。基本上,它是一个演示扩展,可将 Angular 支持的内容脚本加载到任何 http: 中。/https:每当单击浏览器操作按钮时页面。

该扩展采取了所有必要的预防措施,以免干扰(或被破坏)页面自己的 Angular 实例(如果有)。

最后,我必须添加第三个要求(请参阅上面更新的解决方案描述)以保护/隐藏页面的 Angular 实例中的内容脚本的 Angular 应用程序。
(即,我使用 ngNonBindable 指令将根元素包装在父元素中。)

list .json:

{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",

"background": {
"persistent": false,
"scripts": ["background.js"]
},

"browser_action": {
"default_title": "Test Extension"
// "default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
// },
},

"permissions": ["activeTab"]
}

background.js:

// Inject our Angular app, taking care
// not to interfere with page's Angular (if any)
function injectAngular(tabId) {
// Prevent immediate automatic bootstrapping
chrome.tabs.executeScript(tabId, {
code: 'window.name = "NG_DEFER_BOOTSTRAP!" + window.name;'
}, function () {
// Inject AngularJS
chrome.tabs.executeScript(tabId, {
file: 'angular-1.2.7.min.js'
}, function () {
// Inject our app's script
chrome.tabs.executeScript(tabId, {file: 'content.js'});
});
});
}

// Call `injectAngular()` when the user clicks the browser-action button
chrome.browserAction.onClicked.addListener(function (tab) {
injectAngular(tab.id);
});

content.js:

// Create a non-bindable wrapper for the root element
// to keep the page's Angular instance away
var div = document.createElement('div');
div.dataset.ngNonBindable = '';
div.style.cssText = [
'background: rgb(250, 150, 50);',
'bottom: 0px;',
'font-weight: bold;',
'position: fixed;',
'text-align: center;',
'width: 100%;',
''].join('\n');

// Create the app's root element (everything else should go in here)
var appRoot = document.createElement('div');
appRoot.dataset.ngController = 'MyCtrl as ctrl';
appRoot.innerHTML = 'Angular says: {{ctrl.message}}';

// Insert elements into the DOM
document.body.appendChild(div);
div.appendChild(appRoot);

// Angular-specific code goes here (i.e. defining and configuring
// modules, directives, services, filters, etc.)
angular.
module('myApp', []).
controller('MyCtrl', function MyCtrl() {
this.message = 'Hello, isolated world !';
});

/* Manually bootstrap the Angular app */
window.name = ''; // To allow `bootstrap()` to continue normally
angular.bootstrap(appRoot, ['myApp']);
console.log('Boot and loaded !');

<子>细则:
我已经进行了一些初步测试(使用 Angular 和非 Angular 网页),一切似乎都按预期工作。然而,我从未彻底测试过这种方法!


如果有人感兴趣, this is what it took 以“Angular 化”Genie 的灯。

关于javascript - 在已经使用 Angular 的页面上的扩展中使用 Angular,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21048891/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com