我有这个模块,它将外部库与额外的逻辑组件化,而不直接将<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动态加载脚本?
@ 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
我已经修改了@rahul kumars的答案,所以它使用可观察的代替:
import { Injectable } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { Observer } from "rxjs/Observer";
@Injectable()
export class ScriptLoaderService {
private scripts: ScriptModel[] = [];
public load(script: ScriptModel): Observable<ScriptModel> {
return new Observable<ScriptModel>((observer: Observer<ScriptModel>) => {
var existingScript = this.scripts.find(s => s.name == script.name);
// Complete if already loaded
if (existingScript && existingScript.loaded) {
observer.next(existingScript);
observer.complete();
}
else {
// Add the script
this.scripts = [...this.scripts, script];
// Load the script
let scriptElement = document.createElement("script");
scriptElement.type = "text/javascript";
scriptElement.src = script.src;
scriptElement.onload = () => {
script.loaded = true;
observer.next(script);
observer.complete();
};
scriptElement.onerror = (error: any) => {
observer.error("Couldn't load script " + script.src);
};
document.getElementsByTagName('body')[0].appendChild(scriptElement);
}
});
}
}
export interface ScriptModel {
name: string,
src: string,
loaded: boolean
}
嗨,你可以使用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()中进行调用,这是非常有用的。
@d123546
我遇到了同样的问题,现在使用ngAfterContentInit(生命周期钩子)在组件中工作,就像这样:
import { Component, OnInit, AfterContentInit } from '@angular/core';
import { Router } from '@angular/router';
import { ScriptService } from '../../script.service';
@Component({
selector: 'app-players-list',
templateUrl: './players-list.component.html',
styleUrls: ['./players-list.component.css'],
providers: [ ScriptService ]
})
export class PlayersListComponent implements OnInit, AfterContentInit {
constructor(private router: Router, private script: ScriptService) {
}
ngOnInit() {
}
ngAfterContentInit() {
this.script.load('filepicker', 'rangeSlider').then(data => {
console.log('script loaded ', data);
}).catch(error => console.log(error));
}
这个解决方案对我很有效:
1)创建一个名为URLLoader的新类
export class URLLoader {
constructor() {
}
loadScripts() {
const dynamicScripts = [
'URL 1',
'URL 2',
'URL n'
];
for (let i = 0; i < dynamicScripts.length; i++) {
const node = document.createElement('script');
node.src = dynamicScripts[i];
node.type = 'text/javascript';
node.async = false;
node.charset = 'utf-8';
document.getElementsByTagName('app-root')[0].appendChild(node);
}
}
}
2)扩展类URLLoader并从组件类中调用loadScripts方法
export class AppComponent extends URLLoader implements OnInit {
constructor(){}
ngOnInit() {
super.loadScripts();
}
}
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"
]