首页 > 解决方案 > 错误类型错误:i.createShadowRoot 不是 Angular Web 组件上的函数?

问题描述

我正在尝试一个基本的 Angular Web 组件。我创建了一个 github 存储库,在这里展示了该方法:

https://github.com/fireflysemantics/fs-gist

这是组件: https ://github.com/fireflysemantics/fs-gist/blob/master/src/app/fs-gist/fs-gist.component.ts

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'fs-gist',
  template: `
    <p>
      fs-gist works!
    </p>
  `,
  styles: [
  ],
  encapsulation: ViewEncapsulation.Native
})
export class FsGistComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

这是模块: https ://github.com/fireflysemantics/fs-gist/blob/master/src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { FsGistComponent } from './fs-gist/fs-gist.component';

import { Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';

@NgModule({
  declarations: [
    FsGistComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  entryComponents: [FsGistComponent]
})
export class AppModule {
  constructor(private injector: Injector) {}

  ngDoBootstrap() {
    const el = createCustomElement(
      FsGistComponent, 
      { injector: this.injector });
    customElements.define('fs-gist', el);
  }
}

这些是构建脚本package.json

https://github.com/fireflysemantics/fs-gist/blob/master/package.json

    "b": "ng build --prod --output-hashing=none",
    "c": "bash -c 'cat dist/fs-gist/{runtime-es5,polyfills-es5,main-es5}.js > fs-gist.js'",
    "c1": "bash -c 'cat dist/fs-gist/{runtime-es2015,polyfills-es2015,main-es2015}.js > fs-gist2015.js'",
    "p": "npm run b && npm run c",
    "p1": "npm run b && npm run c1",
    "cp-fs-gist": "cp fs-gist.js ../wctest/src/assets/js/"

运行将在根文件夹中npm run p创建 Web 组件。fs-gist

然后我将它复制到src/assets/js/这个测试项目的文件夹中:

https://github.com/fireflysemantics/wc-test

加载应用程序时,控制台日志:

fs-gist.js:1 ERROR TypeError: i.createShadowRoot is not a function at new n (fs-gist.js:1) at e.value (fs-gist.js:1) at fs-gist.js:1在 n.value (fs-gist.js:1) 在 e.value (fs-gist.js:1) 在 e.value (fs-gist.js:1) 在 HTMLElement.value (fs-gist.js: 1) 在 ZoneDelegate.invoke (zone-evergreen.js:364) 在 Object.onInvoke (fs-gist.js:1) 在 ZoneDelegate.invoke (zone-evergreen.js:363)

我在以下位置包含了 web 组件的 polyfill polyfills.js

import "@webcomponents/custom-elements/src/native-shim";
import "@webcomponents/custom-elements/custom-elements.min";
import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js'

我已将 Web 组件加载添加到index.html


  <script src="webcomponents/webcomponents-loader.js"></script>
  <script>   
  if ( !window.customElements ) 
  { document.write('<!--') } 
  </script>
  <script src="webcomponents/custom-elements-es5-adapter.js"></script> 
  <!-- ! KEEP ME -->

有任何想法吗?

也只是为了看看我是否可以在最小的环境中工作,我fs-gist使用了第一个项目生成的 Web 组件并用它制作了一个最小的 javascript stackblitz。

该演示从 CDN 导入 Web 组件 polyfill。

就是这个:

https://stackblitz.com/edit/js-custome-element-test

产生以下错误:

ERROR 错误:无法在“CustomElementRegistry”上执行“define”:名称“fs-gist”已用于此注册表

错误报告

我认为 Web 组件的 Angular 编译存在错误。

https://github.com/angular/angular-cli/issues/17448

标签: angulartypescriptweb-componentangular-elements

解决方案


组件视图封装需要是ViewEncapsulation.ShadowDom(参见上面提到的错误报告以供参考):

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'fs-gist',
  template: `
    <p>
      fs-gist works!
    </p>
  `,
  styles: [
  ],
  encapsulation: ViewEncapsulation.ShadowDom
})
export class FsGistComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}



推荐阅读