2017-05-26 115 views
10

我正在使用Angular 4和CLI创建一个Angular应用程序。我正在尝试将SkyScanner搜索小部件添加到我的某个组件中。实施动态加载来自Angular组件的外部JavaScript文件

Skyscanner Widget Example

部分需要添加一个新的外部脚本:

<script src="https://widgets.skyscanner.net/widget-server/js/loader.js" async></script> 

我不知道的引用此文件的正确方法。如果我将脚本添加到我的index.html文件中,则除非执行完整页面刷新,否则不会加载小部件。我假设脚本试图在加载时操作DOM,并且脚本运行时元素不存在。

只有在加载包含Skyscanner小部件的组件时才加载脚本的正确方法是什么?

回答

20

尝试以下面的方式加载组件加载脚本:

loadAPI: Promise<any>; 

constructor() {   
    this.loadAPI = new Promise((resolve) => { 
     this.loadScript(); 
     resolve(true); 
    }); 
} 

public loadScript() {   
    var isFound = false; 
    var scripts = document.getElementsByTagName("script") 
    for (var i = 0; i < scripts.length; ++i) { 
     if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) { 
      isFound = true; 
     } 
    } 

    if (!isFound) { 
     var dynamicScripts = ["https://widgets.skyscanner.net/widget-server/js/loader.js"]; 

     for (var i = 0; i < dynamicScripts .length; i++) { 
      let node = document.createElement('script'); 
      node.src = dynamicScripts [i]; 
      node.type = 'text/javascript'; 
      node.async = false; 
      node.charset = 'utf-8'; 
      document.getElementsByTagName('head')[0].appendChild(node); 
     } 

    } 
} 
+0

这看起来像迄今为止的最佳答案。谢谢。对loadScript的调用应该在构造函数中,还是在ngOnInit中更好? – psych

+0

我没有[尝试ngOnInit,但如果它适用于INIT,那么最好的地方放在那里 –

+0

但这个文件加载得到延迟,所以我的功能呈现没有这方面的知识。后来它装载没用。如何解决这个问题。 –

2

添加loader.js到您的资产文件夹,然后在你的angular-cli.json

"scripts": ["./src/assets/loader.js",] 

然后添加到您的typings.d.ts

declare var skyscanner:any; 

,你将能够使用它

skyscanner.load("snippets","2"); 
+0

是否最后一行我添加(skyscanner.load ...)被添加到组件中?假设是这样,我看到一个错误,说找不到名称skyscanner。 – psych

0

你可以做一件事

,如果你有角cli.json

,那么你可以声明脚本

"scripts": ["../src/assets/js/loader.js"] 

然后声明在Skyscanner上您的组件

like

declare var skyscanner:any; 

这就是它!

希望这有助于你

+0

我在本地添加了脚本,并将其包含在angular-cli.json文件中。不幸的是,这是行不通的。请你能解释一下将该声明添加到组件中的原因是什么? – psych

3

我已经做了这个代码片断

addJsToElement(src: string): HTMLScriptElement { 
    const script = document.createElement('script'); 
    script.type = 'text/javascript'; 
    script.src = src; 
    this.elementRef.nativeElement.appendChild(script); 
    return script; 
    } 

然后调用它像这样

this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload =() => { 
     console.log('SkyScanner Tag loaded'); 
} 
0

您可以创建自己的指令加载脚本低于

import { Directive, OnInit, Input } from '@angular/core'; 

@Directive({ 
    selector: '[appLoadScript]' 
}) 
export class LoadScriptDirective implements OnInit{ 

    @Input('script') param: any; 

    ngOnInit() { 
     let node = document.createElement('script'); 
     node.src = this.param; 
     node.type = 'text/javascript'; 
     node.async = false; 
     node.charset = 'utf-8'; 
     document.getElementsByTagName('head')[0].appendChild(node); 
    } 

} 

而且你可以在你的组件模板中的任何地方使用它,如下

<i appLoadScript [script]="'script_file_path'"></i> 

例如,动态加载的JQuery在您的组件,在组件的模板中插入下面的代码

<i appLoadScript [script]="'/assets/baker/js/jquery.min.js'"></i>