问题
In angular 2 one can load CSS styles depending on the component. However, there is no corresponding way to load script files. I am currently loading all scripts on the base page of my single page applications but that results in optimization issues.
What is the advised way of loading scripts for an Angular 2/4 component.
回答1:
Well you can load script dynamically in any component.
Here is the solution :
Create a service in which you'll have js file.
// script.store.ts interface Scripts { name: string; src: string; } export const ScriptStore: Scripts[] = [ { name: 'moment', src: 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js' }, { name: 'datatables', src: 'https://cdn.datatables.net/v/dt/dt-1.10.12/datatables.min.js' } ];Now create a service that will load & return the status of the script.
// script.service.ts import { Injectable } from '@angular/core'; import { ScriptStore } from './script.store'; declare var document: any; declare var jQuery: any; @Injectable() export class Script { public scripts: any = {}; 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); } }); } constructor() { ScriptStore.forEach((script: any) => { this.scripts[script.name]={ loaded: false, src: script.src }; }); } }Now you just need to import & call the service.
// import import {Script} from './script.service'; // specify the path where you have created the service // Now call service ngAfterViewInit() { this._script.load('datatables') .then((data:any )=>{ console.log(data,'script loaded') }) .catch((error)=>{ }); }
It will dynamically add the script of 'datatables'.
This only serves your purpose but also it will load only where it is necessary.
回答2:
You can load multiple scripts dynamically like this in your component.ts file:
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);
}
}
and call this method inside the constructor,
constructor() {
this.loadScripts();
}
Note : For more scripts to be loaded dynamically, add them to dynamicScripts array.
来源:https://stackoverflow.com/questions/45294322/angular-2-4-loading-scripts-dynamically