首页 文章

从Angular组件动态加载外部javascript文件

提问于
浏览
23

我正在使用Angular 4和CLI创建一个Angular应用程序 . 我正在尝试将SkyScanner搜索小部件添加到我的一个组件中 .

Skyscanner Widget Example

部分实现需要添加新的外部脚本:

<script src="https://widgets.skyscanner.net/widget-server/js/loader.js" async></script>

我不确定引用此文件的正确方法 . 如果我将脚本添加到index.html文件中,除非执行整页刷新,否则不会加载窗口小部件 . 我假设脚本尝试在加载时操作DOM,并且脚本运行时元素不存在 .

仅在加载包含Skyscanner窗口小部件的组件时加载脚本的正确方法是什么?

7 回答

  • 5

    你可以做一件事

    如果你有angular-cli.json

    然后你可以声明脚本

    喜欢

    "scripts": ["../src/assets/js/loader.js"]
    

    然后在组件中声明skyscanner

    喜欢

    declare var skyscanner:any;
    

    而已!

    希望这对你有所帮助

  • 1

    我已完成此代码段

    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');
    }
    

    EDIT: 使用新的渲染器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;
      }
    

    StackBlitz

  • 5

    注意:这是专门用于外部js链接!步骤1.建议您将角度脚本添加到身体底部的index.html文件中!我尝试了所有其他方法但失败了 .

    <!-- File Name: index.html and its inside src dir-->
    
    <body class="">
      <app-root></app-root>
    
        <!-- Icons -->
            <script src="https://unpkg.com/feather-icons/dist/feather.min.js"></script>
    
    </body>
    

    接下来有两种方法可以执行此操作...在Anguar5中,在此代码中的顶部类型的组件文件夹中使用

    declare var feather:any;
    

    然后在你的课堂内调用你需要的方法 . 例如

    //FileName: dashboard.component.ts
    import { Component, OnInit } from '@angular/core';
    declare var feather:any;
    export class DashboardComponent implements OnInit{
        ngOnInit(){
            feather.replace();
        }
    }
    

    这应该运行你的代码!另一种可能适用于旧版本的方式 . 我没有检查过!

    //FileName: dashboard.component.ts
    import { Component, OnInit } from '@angular/core';
    
    export class DashboardComponent implements OnInit{
    
         ngOnInit(){
        
        
            let node = document.createElement('script');
            node.innerText='feather.replace()';
            node.type = 'text/javascript';
            node.async = false;
            node.charset = 'utf-8';
            
            document.getElementsByTagName('body')[0].appendChild(node);
        
        }
    
    }
    

    如果你没有得到我的代码,那么也尝试这个link .

    希望这可以帮助!

  • 8

    loader.js 添加到您的资源文件夹,然后添加到 angular-cli.json

    "scripts": ["./src/assets/loader.js",]
    

    然后将其添加到 typings.d.ts

    declare var skyscanner:any;
    

    你就可以使用它了

    skyscanner.load("snippets","2");
    
  • 0

    我有同样的问题,但在我的情况下,我在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 -->
    

    如上所述,它没有用 . 然后,我找到帮助我的东西:Milad response

    • 删除app.component.html中的脚本调用 . 您必须在app.component.ts文件中链接这些脚本 .

    • 在ngOnInit()中,使用方法追加库,例如:

    ``

    <!-- app.component.ts -->
    
    export class AppComponent implements OnInit {
       title = 'app';
       ngOnInit() {
         this.loadScript('http://www.some-library.com/library.js');
         this.loadScript('../assets/js/my-library.js');
       }
      }
    
      public loadScript(url: string) {
        const body = <HTMLDivElement> document.body;
        const script = document.createElement('script');
        script.innerHTML = '';
        script.src = url;
        script.async = false;
        script.defer = true;
        body.appendChild(script);
      }
    }
    

    它对我有用 . 我使用Angular 6,希望它有所帮助 .

  • 38

    尝试在组件加载上加载外部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);
            }
    
        }
    }
    
  • 0

    您可以创建自己的 directive 来加载脚本,如下所示

    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>
    

相关问题