我有这个模块,它将外部库与额外的逻辑组件化,而不直接将<script>标记添加到index.html中:

import 'http://external.com/path/file.js'
//import '../js/file.js'

@Component({
    selector: 'my-app',
    template: `
        <script src="http://iknow.com/this/does/not/work/either/file.js"></script>
        <div>Template</div>`
})
export class MyAppComponent {...}

我注意到ES6规范的导入是静态的,并且是在TypeScript编译期间解析的,而不是在运行时。

总之,让它变得可配置,这样file。js就会从CDN或本地文件夹加载? 如何告诉Angular 2动态加载脚本?


当前回答

Angular有防止用户直接干扰html输出的逻辑。所以你必须让Angular通过在Angular中给出那个方向来注入标签。json文件。

首先,您必须获取脚本文件。有两种方法:

下载脚本文件(例如。somelibrary.js)

把它放在资产文件夹中 把脚本的相对路径,放到angular的“scripts”部分。json文件:

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

使用npm/yarn安装脚本:

把脚本的相对路径,放到angular的“scripts”部分。json文件:

"scripts": [
  "./node_modules/somelibrary/dist/somelibrary.min.js"
]

其他回答

如果你正在使用system.js,你可以在运行时使用System.import():

export class MyAppComponent {
  constructor(){
    System.import('path/to/your/module').then(refToLoadedModule => {
      refToLoadedModule.someFunction();
    }
  );
}

如果你正在使用webpack,你可以充分利用它强大的代码分割支持。确保:

export class MyAppComponent {
  constructor() {
     require.ensure(['path/to/your/module'], require => {
        let yourModule = require('path/to/your/module');
        yourModule.someFunction();
     }); 
  }
}

我已经用新的渲染器api完成了这个代码片段

 constructor(private renderer: Renderer2){}

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

然后像这样叫它

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

堆栈闪电战

嗨,你可以使用Renderer2和elementRef只需几行代码:

constructor(private readonly elementRef: ElementRef,
          private renderer: Renderer2) {
}
ngOnInit() {
 const script = this.renderer.createElement('script');
 script.src = 'http://iknow.com/this/does/not/work/either/file.js';
 script.onload = () => {
   console.log('script loaded');
   initFile();
 };
 this.renderer.appendChild(this.elementRef.nativeElement, script);
}

onload函数可以用来在脚本加载后调用脚本函数,如果你必须在ngOnInit()中进行调用,这是非常有用的。

在我的例子中,我使用上述技术加载了js和css visjs文件-这非常有效。我从ngOnInit()中调用新函数

注意:我不能通过简单地添加一个<script>和<link>标签到html模板文件来加载它。

loadVisJsScript() { console.log('Loading visjs js/css files...'); let script = document.createElement('script'); script.src = "../../assets/vis/vis.min.js"; script.type = 'text/javascript'; script.async = true; script.charset = 'utf-8'; document.getElementsByTagName('head')[0].appendChild(script); let link = document.createElement("link"); link.type = "stylesheet"; link.href = "../../assets/vis/vis.min.css"; document.getElementsByTagName('head')[0].appendChild(link); }

@ rahull -kumar的解决方案对我来说很好,但我想在我的typescript中调用我的javascript函数

foo.myFunctions() // works in browser console, but foo can't be used in typescript file

我通过在我的typescript中声明它来修复它:

import { Component } from '@angular/core';
import { ScriptService } from './script.service';
declare var foo;

现在,我可以在typcript文件的任何地方调用foo