我有这个模块,它将外部库与额外的逻辑组件化,而不直接将<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动态加载脚本?
@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();
}
}
如果你正在使用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();
});
}
}
import { Injectable } from '@angular/core';
import * as $ from 'jquery';
interface Script {
src: string;
loaded: boolean;
}
@Injectable()
export class ScriptLoaderService {
public _scripts: Script[] = [];
/**
* @deprecated
* @param tag
* @param {string} scripts
* @returns {Promise<any[]>}
*/
load(tag, ...scripts: string[]) {
scripts.forEach((src: string) => {
if (!this._scripts[src]) {
this._scripts[src] = { src: src, loaded: false };
}
});
const promises: any[] = [];
scripts.forEach(src => promises.push(this.loadScript(tag, src)));
return Promise.all(promises);
}
/**
* Lazy load list of scripts
* @param tag
* @param scripts
* @param loadOnce
* @returns {Promise<any[]>}
*/
loadScripts(tag, scripts, loadOnce?: boolean) {
debugger;
loadOnce = loadOnce || false;
scripts.forEach((script: string) => {
if (!this._scripts[script]) {
this._scripts[script] = { src: script, loaded: false };
}
});
const promises: any[] = [];
scripts.forEach(script => promises.push(this.loadScript(tag, script, loadOnce)));
return Promise.all(promises);
}
/**
* Lazy load a single script
* @param tag
* @param {string} src
* @param loadOnce
* @returns {Promise<any>}
*/
loadScript(tag, src: string, loadOnce?: boolean) {
debugger;
loadOnce = loadOnce || false;
if (!this._scripts[src]) {
this._scripts[src] = { src: src, loaded: false };
}
return new Promise((resolve, _reject) => {
// resolve if already loaded
if (this._scripts[src].loaded && loadOnce) {
resolve({ src: src, loaded: true });
} else {
// load script tag
const scriptTag = $('<script/>')
.attr('type', 'text/javascript')
.attr('src', this._scripts[src].src);
$(tag).append(scriptTag);
this._scripts[src] = { src: src, loaded: true };
resolve({ src: src, loaded: true });
}
});
}
reloadOnSessionChange() {
window.addEventListener('storage', function(data) {
if (data['key'] === 'token' && data['oldValue'] == null && data['newValue']) {
document.location.reload();
}
});
}
}
您可以像这样在组件中动态加载多个脚本。ts文件:
loadScripts() {
const dynamicScripts = [
'https://platform.twitter.com/widgets.js',
'../../../assets/js/dummyjs.min.js'
];
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('head')[0].appendChild(node);
}
}
并在构造函数中调用这个方法,
constructor() {
this.loadScripts();
}
注意:如果需要动态加载更多脚本,请将它们添加到dynamicScripts数组中。