RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 919900
Accepted
lzhec
lzhec
Asked:2020-12-14 16:55:32 +0000 UTC2020-12-14 16:55:32 +0000 UTC 2020-12-14 16:55:32 +0000 UTC

一个组件中有两个指令。冲突

  • 772

大家下午好!

我的任务是在一个组件中加载两个外部模块。我通过渲染指令加载外部脚本。问题是只加载了最后一个,加载时第一个被“覆盖”。当我创建一个新元素时,我发现这都是关于渲染的。如何解决?

home.component.html

<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="nav-home-tab">
  <searchTourSimple [script]="'src/app/scripts/homeSearch.js'"></searchTourSimple>
</div>
<div class="shop-window">
  <div id="shopwindow-container">
    <shopWindow [script]="'src/app/scripts/shopwindow.js'"></shopWindow>
  </div>
</div>

dir1.directive.ts

@Directive({
  selector: 'searchTourSimple'
})

export class SearchModuleSimpleDirective implements OnInit {
  @Input('script') param: any
  script: any

  constructor(private renderer:Renderer2) { }

  ngOnInit() {

    this.script = this.renderer.createElement('script')     
    this.script.type = 'text/javascript'    
    this.script.src = this.param
    this.script.async = true
    this.renderer.appendChild(document.head, this.script)

    document.write = function(input: string) {
      document.getElementById('home').innerHTML += input
    }
  }
}

dir2.directive.ts

@Directive({
  selector: 'shopWindow'
})

export class ShopWindowDirective implements OnInit {
  @Input('script') param: any
  script: any

  constructor(private renderer:Renderer2) { }

  ngOnInit() {

    this.script = this.renderer.createElement('script')
    this.script.type = 'text/javascript'
    this.script.src = this.param
    this.script.async = true
    this.renderer.appendChild(document.head, this.script)

    document.write = function(input: string) {
      document.getElementById('shopwindow-container').innerHTML += input
    }
  }
}
angular
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    overthesanity
    2020-12-17T07:07:06Z2020-12-17T07:07:06Z

    你的问题是第二个指令也补丁document.write,所以第一个指令已经使用了第二个指令修补的方法并将其设置innerHTML为document.getElementById('shopwindow-container').

    这里不需要指令,如果我从源代码中理解正确,那么您正在尝试使用指令加载外部资源.js,您通常需要将此业务逻辑隔离到某种服务中,我们称之为ScriptService:

    import { Injectable } from '@angular/core';
    
    import { Observable, of } from 'rxjs';
    import { tap, switchMap } from 'rxjs/operators';
    
    @Injectable({ providedIn: 'root' })
    export class ScriptService {
        private loadResource(src: string): Observable<void> {
            return new Observable((observer) => {
                const script = document.createElement('script');
    
                script.async = true;
                script.src = src;
    
                script.addEventListener('load', () => {
                    observer.next();
                    observer.complete();
                });
    
                document.head.appendChild(script);
            });
        }
    
        private patchDocumentWrite(id: string): void {
            document.write = (input: string): void => {
                document.getElementById(id).innerHTML += input;
            };
        }
    
        public loadExternalResources(): Observable<void> {
            return of(null).pipe(
                tap(() => this.patchDocumentWrite('home')),
                switchMap(() => this.loadResource('src/app/scripts/homeSearch.js')),
                tap(() => this.patchDocumentWrite('shopwindow-container')),
                switchMap(() => this.loadResource('src/app/scripts/shopwindow.js'))
            );
        }
    }
    

    我们在做什么?该方法loadResource返回一个流,并在外部资源 ( onload) 完全加载后触发一个事件。patchDocumentWrite- 只是补丁document.write,并将要设置的元素的标识符作为参数innerHTML。在方法loadExternalResources中,我们创建了一个空流(后续管道需要)。在加载脚本之前,homeSearch我们将对其进行修补document.write并以相同的方式继续。

    在这个实现中,我们一个一个地加载脚本,但这给了我们一个保证,一个指令不会比另一个更快地修补方法。我们也不使用Renderer2它(这不是必需的)。现在我们需要订阅该方法返回的流loadExternalResources以运行整个管道,我们可以在ngAfterViewInit组件的根目录中执行此操作:

    export class AppComponent implements AfterViewInit {
        constructor(private scriptService: ScriptService) {}
    
        public ngAfterViewInit(): void {
            this.scriptService.loadExternalResources().subscribe(() => {
                console.log('все скрипты загрузились');
            });
        }
    }
    
    • 0

相关问题

  • Angular CLI 和材料表

  • 角。上下文菜单

  • 导航到另一个页面Angular 6时记住树状态

  • 将数据从组件传递到服务。角 2

  • 角 6 错误 500

  • 为什么@input 不能以角度工作

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5