首页 > 解决方案 > 使 JavaScript 脚本可用于影子 DOM

问题描述

是否可以在影子 DOM 中启用 JavaScript?我已经尝试了以下方法,但它不起作用。如果没有,有什么替代方案:

@Component({
  selector: 'app-website-layout',
  templateUrl: './website-layout.component.html',
  encapsulation: ViewEncapsulation.ShadowDom
})
export class WebsiteLayoutComponent implements OnInit, AfterViewInit {
    private static appendCssToShadowRoot(shadowRoot, src) {
    const link = document.createElement('link');
    link.setAttribute('rel', 'stylesheet');
    link.setAttribute('href', src);
    link.setAttribute('type', 'text/css');
    shadowRoot.prepend(link);
  }

  private static appendJs(src) {
    const script = document.createElement('script');
    script.src = src;
    document.getElementsByTagName('head')[0].appendChild(script);
  }

  ngAfterViewInit() {
    const shadowRoot: DocumentFragment = this.element.nativeElement.shadowRoot;
    WebsiteLayoutComponent.appendJs('https://code.jquery.com/jquery-3.4.1.min.js');
    WebsiteLayoutComponent.appendJs('https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js');
    WebsiteLayoutComponent.appendJs('https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js');
    WebsiteLayoutComponent.appendCssToShadowRoot(shadowRoot, 'assets/css/website.css');
    WebsiteLayoutComponent.appendCssToShadowRoot(shadowRoot, 'assets/css/page.css');
    WebsiteLayoutComponent.appendCssToShadowRoot(shadowRoot, 'assets/css/fonts.css');
  } 
}

我也尝试了以下方法,但它不起作用

  private static appendJsToShadowRoot(shadowRoot, src) {
    const link = document.createElement('script');
    link.setAttribute('src', src);
    shadowRoot.prepend(link);
  }

  WebsiteLayoutComponent.appendJsToShadowRoot(shadowRoot, 'assets/js/popper.min.js');
  WebsiteLayoutComponent.appendJsToShadowRoot(shadowRoot, 'assets/js/bootstrap.min.js');
  WebsiteLayoutComponent.appendJsToShadowRoot(shadowRoot, 'assets/js/jquery.min.js');

但是,我可以确认以下内容

  WebsiteLayoutComponent.appendJsToShadowRoot(shadowRoot, 'assets/js/test.js');

test.js 的内容在哪里

alert('hello');

奇怪的是,它不适用于 jquery 和 bootstrap,即使我在 HTML 源代码中看到它们。

在此处输入图像描述

标签: javascriptangular

解决方案


由于库依赖于文档根而不是 shadowroot,因此需要覆盖代码中的文档变量。我最近遇到了一个类似的问题,但它不包括大型库。您可以检查这是否适合您:

function documentParse() {
   var element = document.getElementById('shadow_root').shadowRoot
   element.createElement = function createElement(type) {
      return document.createElement(type)
   }
   element.head = document.head
   return element
}

script.textContent = `(function(document) {
 //script source text
}(documentParse()));`

....

以这种方式包装脚本将使对文档的每次搜索都进入 shadowroot dom 内的元素范围。您可能还需要克隆其他文档功能。

来源:重命名 var 文档。在 shadow root 中运行 Js


推荐阅读