【问题标题】:elementRef is null after building angular app构建角度应用程序后 elementRef 为空
【发布时间】:2019-04-23 02:01:45
【问题描述】:

在组件模板中,我正在使用 ElementRef 选择一个 svg 元素。它工作正常,但是当我构建应用程序并打开它时 elementRef 为空。

    @Component({
      selector: 'app-svg',
      template: `<div id="root">
        <object [data]='trustedUrl' type="image/svg+xml" height="450" width="650" #dataSvg></object>
      </div>`,
      styleUrls: ['./svg.component.css'] 

    })
constructor(private sanitizer: DomSanitizer, private elRef: ElementRef) {    
 }

elementRef 目标

@ViewChild('dataSvg') dataSvg: ElementRef;

将它传递给 elementRef 变量

ngOnInit() {
    this.elementRef = this.elRef.nativeElement.querySelector('#dataSvg');  
     }

加载内容后,我正在选择 svg:

ngAfterContentInit() {
    const elementRef = this.elementRef;

    // when content is loaded...
    elementRef.addEventListener('load', function (event) {
      // ...retrieve svg element

elementRef.querySelector('svg') 为空

当我运行“npm run build”并转到 dist/index.html 时,contentDocument> 为空

【问题讨论】:

    标签: angular dom elementref


    【解决方案1】:

    DOM 尚未完全构建在 ngOnInit 中。您需要等待子项(此处为模板)被创建。

    将您的代码放入ngAfterViewInit,而不是ngOnInit

    关于组件生命周期中的钩子的更多信息可以找到in the Angular documentation

    【讨论】:

    • 谢谢,我在 AfterViewInit 上进行了更改,但是当我编译应用程序(npm run build)并将 index.html 打开到 /dist elementRef 时为空。我想选择对象元素(elementRef.nativeElement.contentDocument)的svg子元素
    【解决方案2】:

    根据 official Doc,您无法访问 @ViewChild 元素,除非您在 AfterView 挂钩(AfterViewInit 或 @987654326 @ ) 而不是 OnInit 之一。


    • You can find here 一篇关于@ViewChild@ViewChildren@ContentChild@ContentChildren 之间差异的好文章。

    【讨论】:

      【解决方案3】:

      您使用了@ViewChild('dataSvg') dataSvg: ElementRef;,但在您的模板中您没有为dataSvg 提供任何锚点。

      有两种方法可以做到这一点: 1) 按照Angular Docs 的说明使用@Directive 2)使用模板引用#:在你的情况下: &lt;object ... #dataSvg&gt;&lt;/object&gt;

      如果您已经使用 Directive,则未提及,但在您的模板代码中,您只有一个 id=dataSvg

      【讨论】:

      • 呃,但是现在您已经删除了 ID 部分,因此:this.elementRef = this.elRef.nativeElement.querySelector('#dataSvg'); 将不再起作用。我不太确定,考虑到您已经拥有 @viewchild 参考资料,为什么要这样做
      • 不,它已修复,我使用 elementRef this.dataSvg。问题出在前台..当它不在节点中运行时,我失去了动态comportment。 SVG 未加载动态组件工厂
      【解决方案4】:

      我找到了附加 SVG 元素的兼容性解决方案:

      在我的 svg 组件中,我使用绑定 innerHTML 设置 svg 的源,当我的输入发生更改时,我正在使用以安全方式返回 svg 数据的服务加载 svg:

      在组件中绑定SVG的数据源:

       @Component({
        selector: 'app-svg',
        template: `<div id="root">
          <div [innerHTML]="svgSafe" type="image/svg+xml" height="450" width="650" #dataSvg></div>
        </div>`,
        styleUrls: ['./svg.component.css'] ,
        animations: [
      
        ]
      })
      

      使用输入加载 svg 的源代码:

       ngOninit() {
      
          var url = this.data.url;
      
      
          var id = 1; 
      
          if(url === 'assets/object_move.svg') {
             id = 1;
          }
      
          if(url === 'assets/object_wait.svg') {
            id = 2;
          }
      
      
          ..
          var dataSVG;
                  this
                    .loaderService
                    .getSVGData(id)
                    .subscribe((dataSvg) => {
      
            this.svgSafe = this.sanitizer.bypassSecurityTrustHtml(dataSvg.data);
      
                  });
          }
      

      【讨论】:

        【解决方案5】:

        在下面的地方,明确给出读取:ElementRef,

        @ViewChild('dataSvg') dataSvg: ElementRef;

        应该是

        @ViewChild('dataSvg', { read: ElementRef }) dataSvg: ElementRef;

        【讨论】:

          【解决方案6】:

          存在与 ElementRef 相关的安全风险:

          允许直接访问 DOM 会使您的应用程序更容易受到 XSS 攻击。

          https://angular.io/api/core/ElementRef#description

          考虑使用 Renderer2:

          https://angular.io/api/core/Renderer2

          【讨论】:

            猜你喜欢
            • 2020-06-10
            • 1970-01-01
            • 2018-11-29
            • 1970-01-01
            • 2020-09-27
            • 1970-01-01
            • 2016-06-06
            • 2020-05-22
            • 1970-01-01
            相关资源
            最近更新 更多