从Angular组件动态加载外部javascript文件
我正在使用Angular 4和CLI创建Angular应用程序。我正在尝试将SkyScanner搜索小部件添加到我的一个组件中 部分实现需要添加新的外部脚本:从Angular组件动态加载外部javascript文件,angular,typescript,skyscanner,Angular,Typescript,Skyscanner,我正在使用Angular 4和CLI创建Angular应用程序。我正在尝试将SkyScanner搜索小部件添加到我的一个组件中 部分实现需要添加新的外部脚本: <script src="https://widgets.skyscanner.net/widget-server/js/loader.js" async></script> 我不确定引用此文件的正确方式。如果我将脚本添加到index.html文件中,除非执行完整页面刷新,否则不会加载小部件。我假设脚本尝试
<script src="https://widgets.skyscanner.net/widget-server/js/loader.js" async></script>
我不确定引用此文件的正确方式。如果我将脚本添加到index.html文件中,除非执行完整页面刷新,否则不会加载小部件。我假设脚本尝试在加载时操作DOM,并且在脚本运行时元素不存在
只有在加载包含Skyscanner小部件的组件时才加载脚本的正确方法是什么?将
loader.js
添加到您的资产文件夹,然后添加到angular cli.json
"scripts": ["./src/assets/loader.js",]
然后将其添加到您的打字.d.ts
declare var skyscanner:any;
你将能够使用它
skyscanner.load("snippets","2");
尝试在组件加载时加载外部JavaScript,如下所示:
loadAPI: Promise<any>;
constructor() {
this.loadAPI = new Promise((resolve) => {
this.loadScript();
resolve(true);
});
}
public loadScript() {
var isFound = false;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) {
isFound = true;
}
}
if (!isFound) {
var dynamicScripts = ["https://widgets.skyscanner.net/widget-server/js/loader.js"];
for (var i = 0; i < dynamicScripts.length; i++) {
let 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);
}
}
}
loadAPI:Promise;
构造函数(){
this.loadAPI=新承诺((解析)=>{
这个.loadScript();
决心(正确);
});
}
公共加载脚本(){
var isFound=false;
var scripts=document.getElementsByTagName(“脚本”)
对于(变量i=0;i
你可以做一件事
如果您有angular-cli.json
然后您可以向脚本声明
像
然后在组件中声明skyscanner
像
就这样
希望这对您有所帮助我已经完成了这个代码片段
addJsToElement(src: string): HTMLScriptElement {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = src;
this.elementRef.nativeElement.appendChild(script);
return script;
}
然后像这样称呼它
this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload = () => {
console.log('SkyScanner Tag loaded');
}
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;
}
编辑:使用新的渲染器Api,可以这样编写
this.addJsToElement('https://widgets.skyscanner.net/widget-server/js/loader.js').onload = () => {
console.log('SkyScanner Tag loaded');
}
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;
}
您可以创建自己的指令来加载脚本,如下所示
import { Directive, OnInit, Input } from '@angular/core';
@Directive({
selector: '[appLoadScript]'
})
export class LoadScriptDirective implements OnInit{
@Input('script') param: any;
ngOnInit() {
let node = document.createElement('script');
node.src = this.param;
node.type = 'text/javascript';
node.async = false;
node.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(node);
}
}
您可以在组件模板中的任何位置使用它,如下所示
<i appLoadScript [script]="'script_file_path'"></i>
例如,要在组件中动态加载JQuery,请在组件的模板中插入以下代码
<i appLoadScript [script]="'/assets/baker/js/jquery.min.js'"></i>
注意:这是专门针对外部js链接的! 第一步。建议将angular脚本添加到身体底部的index.html文件中!我尝试了所有其他方法,但都失败了
我也遇到了同样的问题,但在我的例子中,我在html文件末尾导入了10个库,这些库有很多方法、侦听器、事件等,在我的例子中,我不需要专门调用方法 关于我的例子:
<!-- app.component.html -->
<div>
...
</div>
<script src="http://www.some-library.com/library.js">
<script src="../assets/js/my-library.js"> <!-- a route in my angular project -->
...
如前所述,它不起作用。然后,我找到了一些帮助我的东西:
导出类AppComponent实现OnInit{
标题=‘应用程序’;
恩戈尼尼特(){
此.loadScript('http://www.some-library.com/library.js');
这个.loadScript('../assets/js/my library.js');
}
}
公共加载脚本(url:string){
const body=document.body;
const script=document.createElement('script');
script.innerHTML='';
script.src=url;
script.async=false;
script.deep=真;
body.appendChild(脚本);
}
}
它对我有用。我使用Angular 6,希望能有所帮助。有点晚了,但我更喜欢这种方式(服务方式) 然后在我的组件中,我可以执行以下操作:
ngOnInit() {
this.fileInjectorService.loadJS('script-a', 'script-c').then(data => {
// Loaded A and C....
}).catch(error => console.log(error));
}
在Angular 6/7中测试,接受的答案是正确的,但不起作用,因为浏览器在下载脚本后解析脚本只需花费很少的时间。因此,如果从加载的脚本中使用任何变量,则需要在新创建的html脚本元素的onload事件中使用该变量。我已经改进了下面提到的公认答案-
loadAPI: Promise<any>;
constructor() {
this.loadAPI = new Promise((resolve) => {
let node = this.loadScript();
if (node) {
node.onload = () => {
resolve(true);
};
} else {
resolve(true);
}
});
}
ngOnInit() {
this.loadAPI
.then((flag) => {
//Do something when script is loaded and parsed by browser
});
}
loadScript() {
let node = undefined;
let isFound = false;
const scripts = document.getElementsByTagName('script')
for (let i = 0; i < scripts.length; ++i) {
// Check if script is already there in html
if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) {
isFound = true;
}
}
if (!isFound) {
const dynamicScript = 'https://widgets.skyscanner.net/widget-server/js/loader.js';
node = document.createElement('script');
node.src = dynamicScript;
node.type = 'text/javascript';
node.async = false;
node.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(node);
return node;
}
return node;
}
loadAPI:Promise;
构造函数(){
this.loadAPI=新承诺((解析)=>{
让node=this.loadScript();
如果(节点){
node.onload=()=>{
决心(正确);
};
}否则{
决心(正确);
}
});
}
恩戈尼尼特(){
这是loadAPI
。然后((标志)=>{
//在浏览器加载和解析脚本时执行某些操作
});
}
loadScript(){
让节点=未定义;
让isFound=false;
const scripts=document.getElementsByTagName('script')
for(设i=0;i
经过这么多的代码测试,这对我来说很有效
ngOnInit() {
this.loadFormAssets().then(() => {console.log("Script Loaded");}).catch(() => {console.log("Script Problem");});
}
public loadFormAssets() {
return new Promise(resolve => {
const scriptElement = document.createElement('script');
scriptElement.src =this.urls.todojs;
scriptElement.onload = resolve;
document.body.appendChild(scriptElement);
const scriptElement1 = document.createElement('script');
scriptElement1.src =this.urls.vendorjs;
scriptElement1.onload = resolve;
document.body.appendChild(scriptElement1);
});
}
在我的例子中,我必须加载一些相互依赖的不同文件(某种使用引导的东西,然后使用jquery插件,然后使用jquery),它们在加载时都立即初始化,假设它们在网页上同步加载。所有其他答案
loadAPI: Promise<any>;
constructor() {
this.loadAPI = new Promise((resolve) => {
let node = this.loadScript();
if (node) {
node.onload = () => {
resolve(true);
};
} else {
resolve(true);
}
});
}
ngOnInit() {
this.loadAPI
.then((flag) => {
//Do something when script is loaded and parsed by browser
});
}
loadScript() {
let node = undefined;
let isFound = false;
const scripts = document.getElementsByTagName('script')
for (let i = 0; i < scripts.length; ++i) {
// Check if script is already there in html
if (scripts[i].getAttribute('src') != null && scripts[i].getAttribute('src').includes("loader")) {
isFound = true;
}
}
if (!isFound) {
const dynamicScript = 'https://widgets.skyscanner.net/widget-server/js/loader.js';
node = document.createElement('script');
node.src = dynamicScript;
node.type = 'text/javascript';
node.async = false;
node.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(node);
return node;
}
return node;
}
ngOnInit() {
this.loadFormAssets().then(() => {console.log("Script Loaded");}).catch(() => {console.log("Script Problem");});
}
public loadFormAssets() {
return new Promise(resolve => {
const scriptElement = document.createElement('script');
scriptElement.src =this.urls.todojs;
scriptElement.onload = resolve;
document.body.appendChild(scriptElement);
const scriptElement1 = document.createElement('script');
scriptElement1.src =this.urls.vendorjs;
scriptElement1.onload = resolve;
document.body.appendChild(scriptElement1);
});
}