javascript - 在 Shadow DOM 中使用 JS 库

标签 javascript angularjs google-chrome-extension shadow-dom

几个小时以来,我一直在努力解决这个问题,但无济于事。

基本上,我正在制作一个 Chrome 扩展,将一堆 HTML 加载到页面中。 为了避免很多问题,我想使用 Shadow DOM 进行封装。 CSS 封装得很好,一段时间后我终于设法将 JS 也加载到 DOM 中。

问题是,我包含了 2 个 JS 文件:

  • vendor.js(我使用的 JS 库,编译成一个文件。著名的库:jQuery 和 Angular)
  • extension.js - 我自己的代码被编译成一个文件(执行一些初始化、引导 Angular 并定义 Controller /指令/等)

问题是,在加载 vendor.js 文件后,我无法访问它在其他脚本中应用的内容。

对于我的生活,我无法弄清楚它登录到哪个上下文并将其用作“窗口”元素以将类注入(inject)到其中。

这是我的 Shadow DOM 初始加载脚本:

// HACK: we need to "bleed" font-faces to outside the shadow dom because of a bug in chrome
document.querySelector('head').innerHTML +=
  '<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />'

let rootElHtml = `
    <div id="cls-root">
      <template id="cls-template">
      </template>
    </div>
  `

document.body.innerHTML += rootElHtml
let rootEl = document.querySelector('#cls-root'),
  templateEl = rootEl.querySelector('template'),
  shadow = rootEl.attachShadow({
    mode: 'open'
  })

let cssLinks = [
  chrome.extension.getURL('dist/css/vendor.css'),
  chrome.extension.getURL('dist/css/extension.css'),
  '//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css'
].map(p => `<link rel="stylesheet" href="${p}" />`).join("\n")

let jsLinks = [
  chrome.extension.getURL('dist/js/vendor.js'),
  chrome.extension.getURL('dist/js/extension.js'),
].map(p => `<script src="${p}" type="text/javascript"></script>`).join("\n")

// inject css/js into template content
let templateNodeContents = document.createElement('div')
templateNodeContents.innerHTML = [cssLinks, jsLinks].join("\n")
for (let node of templateNodeContents.childNodes)
  templateEl.content.appendChild(node)

// load remote HTML template and apply into shadow root template
fetch(chrome.extension.getURL('dist/templates/root.html')).then((data) => {
  data.text().then((body) => {
    let bodyContainer = document.createElement('div')

    shadow.appendChild(document.importNode(templateEl.content, true))
    bodyContainer.innerHTML = body
    shadow.appendChild(bodyContainer.childNodes[0])
  })
})

window._clsExt = shadow

这里是我尝试引导 Angular:

const shadow = document.querySelector('#cls-root').shadowRoot

shadow.APP_NAME = 'myApp'
shadow.app = angular.module(APP_NAME, ['ngStorage'])
  .config(['$localStorageProvider', '$httpProvider',
    ($localStorageProvider, $httpProvider) => {
      $localStorageProvider.setKeyPrefix('myApp');
      $httpProvider.interceptors.push(apiInterceptor);
    }
  ])
shadow.app.constant('APP_ENV', APP_SETTINGS.app_env)
shadow.app.constant('API_BASE', APP_SETTINGS.api_base_url)
angular.bootstrap(shadow, [APP_NAME])

但是,我一直遇到有关 Angular 错误:

extension.js:21 Uncaught ReferenceError: angular is not defined
    at extension.js:21

我尝试在 shadow 元素的属性以及其他 window 变体中四处寻找,并试图在其中找到文档。

如果不强制将文件合并在一起,这可能吗?我希望保持这种分离。

最佳答案

我看到您将 JS 文件添加到 Shadow DOM 范围中。它不起作用,因为访问 Shadow dom 中的元素是不同的,并且库在它们内部不起作用。

当我说访问 DOM 是不同的

$(#id) //the usual way to access a id using jQuery
parentofShadowtree.shadowRoot.querySelector('#id') //to select a element inside shadow DOM

可以看到在Shadow DOM中访问DOM元素是不一样的,一般的JS库文件无法访问元素,在这里不起作用

如果我错了请纠正我。

关于javascript - 在 Shadow DOM 中使用 JS 库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45036240/

相关文章:

javascript - 限制表单提交的次数

javascript - 自定义选择框,如果不是自定义选择框且其子项被点击则向上滑动

javascript - 对同一 URL 进行多个 ajax 请求的奇怪行为

javascript - 最佳实践 Controller /服务

javascript - 为什么 dom 事件在 angularjs 的 Controller 内部不起作用

google-chrome - Chrome 版本 18+ : How to allow inline scripting with a Content Security Policy?

javascript - 我如何在谷歌扩展中打开/关闭 content_scripts?

javascript - SendGrid 客户端 TypeScript 错误 : HttpMethod

javascript - 为什么angularJS不直接给出具体的错误位置,而是给出一个链接到他们的网站链接,给出一些通用的解释?

javascript - 如何从 chrome 扩展中打开的窗口获取背景页面?