Ich habe dieses Modul, das die externe Bibliothek zusammen mit zusätzlicher Logik zu komponieren, ohne das Hinzufügen der <script>
-Tag direkt in die 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 {...}
Mir ist aufgefallen, dass der Import
nach ES6-Spezifikation statisch ist und während der TypeScript-Transpilierung und nicht zur Laufzeit aufgelöst wird.
Kann man das irgendwie konfigurieren, so dass die file.js entweder aus dem CDN oder aus dem lokalen Ordner geladen wird? Wie kann man Angular 2 anweisen, ein Skript dynamisch zu laden?
Sie können die folgende Technik verwenden, um JS-Skripte und -Bibliotheken bei Bedarf dynamisch in Ihr Angular-Projekt zu laden.
script.store.ts enthält den Pfad des Skripts entweder lokal oder auf einem entfernten Server und einen Name, der zum dynamischen Laden des Skripts verwendet wird
interface Scripts {
name: string;
src: string;
}
export const ScriptStore: Scripts[] = [
{name: 'filepicker', src: 'https://api.filestackapi.com/filestack.js'},
{name: 'rangeSlider', src: '../../../assets/js/ion.rangeSlider.min.js'}
];
script.service.ts ist ein injizierbarer Dienst, der das Laden des Skripts übernimmt, kopieren Sie script.service.ts
wie es ist
import {Injectable} from "@angular/core";
import {ScriptStore} from "./script.store";
declare var document: any;
@Injectable()
export class ScriptService {
private scripts: any = {};
constructor() {
ScriptStore.forEach((script: any) => {
this.scripts[script.name] = {
loaded: false,
src: script.src
};
});
}
load(...scripts: string[]) {
var promises: any[] = [];
scripts.forEach((script) => promises.push(this.loadScript(script)));
return Promise.all(promises);
}
loadScript(name: string) {
return new Promise((resolve, reject) => {
//resolve if already loaded
if (this.scripts[name].loaded) {
resolve({script: name, loaded: true, status: 'Already Loaded'});
}
else {
//load script
let script = document.createElement('script');
script.type = 'text/javascript';
script.src = this.scripts[name].src;
if (script.readyState) { //IE
script.onreadystatechange = () => {
if (script.readyState === "loaded" || script.readyState === "complete") {
script.onreadystatechange = null;
this.scripts[name].loaded = true;
resolve({script: name, loaded: true, status: 'Loaded'});
}
};
} else { //Others
script.onload = () => {
this.scripts[name].loaded = true;
resolve({script: name, loaded: true, status: 'Loaded'});
};
}
script.onerror = (error: any) => resolve({script: name, loaded: false, status: 'Loaded'});
document.getElementsByTagName('head')[0].appendChild(script);
}
});
}
}
Injizieren Sie diesen ScriptService
wo immer Sie ihn brauchen und laden Sie js-Libs wie folgt
this.script.load('filepicker', 'rangeSlider').then(data => {
console.log('script loaded ', data);
}).catch(error => console.log(error));
Wenn Sie system.js verwenden, können Sie System.import()
zur Laufzeit verwenden:
export class MyAppComponent {
constructor(){
System.import('path/to/your/module').then(refToLoadedModule => {
refToLoadedModule.someFunction();
}
);
}
Wenn Sie webpack verwenden, können Sie die Vorteile seiner robusten Code-Aufteilung mit require.ensure
voll ausschöpfen:
export class MyAppComponent {
constructor() {
require.ensure(['path/to/your/module'], require => {
let yourModule = require('path/to/your/module');
yourModule.someFunction();
});
}
}
Dies könnte funktionieren. Dieser Code fügt dynamisch den <script>
-Tag an den head
der html-Datei an, wenn auf die Schaltfläche geklickt wird.
const url = 'http://iknow.com/this/does/not/work/either/file.js';
export class MyAppComponent {
loadAPI: Promise<any>;
public buttonClicked() {
this.loadAPI = new Promise((resolve) => {
console.log('resolving promise...');
this.loadScript();
});
}
public loadScript() {
console.log('preparing to load...')
let node = document.createElement('script');
node.src = url;
node.type = 'text/javascript';
node.async = true;
node.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(node);
}
}