<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 {...}
나는 알 import
ES6에 의한 사양은 정적 및 타이프 라이터가 아니라 런타임에보다 transpiling 동안 해결입니다.
어쨌든 file.js가 CDN 또는 로컬 폴더에서로드되도록 구성 할 수 있습니까? Angular 2에게 스크립트를 동적으로로드하도록 지시하는 방법은 무엇입니까?
답변
system.js를 사용 System.import()
하는 경우 런타임에 사용할 수 있습니다 .
export class MyAppComponent {
constructor(){
System.import('path/to/your/module').then(refToLoadedModule => {
refToLoadedModule.someFunction();
}
);
}
웹팩을 사용하는 경우 다음을 통해 강력한 코드 분할 지원을 최대한 활용할 수 있습니다 require.ensure
.
export class MyAppComponent {
constructor() {
require.ensure(['path/to/your/module'], require => {
let yourModule = require('path/to/your/module');
yourModule.someFunction();
});
}
}
답변
다음 기술을 사용하여 Angular 프로젝트에서 요청시 JS 스크립트 및 라이브러리를 동적으로로드 할 수 있습니다.
script.store.ts 는 로컬 또는 원격 서버의 스크립트 경로 와 스크립트를 동적으로로드하는 데 사용되는 이름을 포함 합니다.
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 는 스크립트 로딩을 처리하고 script.service.ts
그대로 복사하는 주입 가능한 서비스 입니다.
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);
}
});
}
}
ScriptService
필요할 때마다 이것을 주입하고 다음 과 같이 js libs를로드하십시오.
this.script.load('filepicker', 'rangeSlider').then(data => {
console.log('script loaded ', data);
}).catch(error => console.log(error));
답변
이 작동 할 수 있습니다. 이 코드는 버튼을 클릭하면 html 파일에 <script>
태그를 동적으로 추가합니다 head
.
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);
}
}
답변
@rahul kumars 답변을 수정하여 대신 Observables를 사용합니다.
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
}
답변
또 다른 옵션은 그 문제에 대한 scriptjs
패키지 를 활용 하는 것입니다.
모든 URL에서 주문형 스크립트 리소스를로드 할 수 있습니다.
예
패키지를 설치하십시오 :
npm i scriptjs
와 정의를위한 입력scriptjs
:
npm install --save @types/scriptjs
그런 다음 가져 오기 $script.get()
방법 :
import { get } from 'scriptjs';
마지막으로 Google Maps 라이브러리에서는 스크립트 리소스를로드합니다.
export class AppComponent implements OnInit {
ngOnInit() {
get("https://maps.googleapis.com/maps/api/js?key=", () => {
//Google Maps library has been loaded...
});
}
}
답변
파일에 다음 과 같이 여러 스크립트를 동적으로 로드 할 수 있습니다 component.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
배열에 추가하십시오 .
답변
새로운 렌더러 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');
}