繁体   English   中英

Angular如何动态加载外部脚本?

[英]How to load external scripts dynamically in Angular?

我有这个模块将外部库与附加逻辑一起组件化,而无需将<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 {...}

我注意到 ES6 规范的import是 static 并在 TypeScript 转译期间而不是在运行时解析。

无论如何使其可配置,以便 file.js 将从 CDN 或本地文件夹加载? 如何告诉 Angular 2 动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我在下面的链接中遇到了同样的问题。我以非常简单的方式解决了它。

https://www.gstatic.com/charts/loader.js

我需要在下面的代码中访问 google 变量。 但是当我把它放在 angular 类中时它不起作用。

google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
    var data = google.visualization.arrayToDataTable([
        ["Element", "Density", { role: "style" } ],
        ["Copper", 8.94, "dodgerblue"],
        ["Silver", 10.49, "dodgerblue"],
        ["Gold", 19.30, "dodgerblue"],
        ["Platinum", 21.45, "color: dodgerblue"]
    ]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
    { calc: "stringify",
        sourceColumn: 1,
        type: "string",
        role: "annotation" },
    2]);

var options = {
    title: "Density of Precious Metals, in g/cm^3",
    width: 600,
    height: 400,
    bar: {groupWidth: "50%"},
    legend: { position: "none" },
};
var chart = new google.visualization.ColumnChart(document.getElementById("columnchart_values"));
chart.draw(view, options);

}

我在 ts 类的顶部创建了一个具有相同名称(google)的全局变量,然后该变量自动引用所需的变量。(因为它是全局范围)然后问题就解决了。

declare var google: any;

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

这个解决方案对我有用:

1 ) 创建一个名为URLLoader的新类

export class URLLoader {
  constructor() {

  }

  loadScripts() {

    const dynamicScripts = [
      'URL 1',
      'URL 2',
      'URL n'
    ];

    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('app-root')[0].appendChild(node);
    }
  }

}

2 ) 扩展类URLLoader并从组件类调用loadScripts方法

export class AppComponent extends URLLoader implements OnInit {  

   constructor(){}

   ngOnInit() {
   super.loadScripts();
   }

}

我发现这个解决方案更简洁,首先在你的模块中导入HttpClientJsonpModule然后做这样的事情

this.apiLoaded = this.httpClient.jsonp(environment.AnyApiUrl, 'callback')
  .pipe(
    map(() => true),
    catchError(() => of(false)),
  );

在您的模板中:

<app-component *ngIf="apiLoaded | async"></app-component>

此解决方案位于此处的官方 Angular Google Maps 文档中。

Angular 具有防止用户直接干扰 html 输出的逻辑。 所以你必须让 Angular 通过在angular.json文件中给出该方向来注入标签。

首先,您必须获取脚本文件。 有两种方法:

  1. 下载脚本文件(例如 somelibrary.js)
  • 将其放在资产文件夹中
  • 将脚本的相对路径放入angular.json文件的“脚本”部分:
"scripts": [
  "src/assets/somelibrary.js"
]
  1. 使用 npm/yarn 安装脚本:
  • 将脚本的相对路径放入angular.json文件的“脚本”部分:
"scripts": [
  "./node_modules/somelibrary/dist/somelibrary.min.js"
]

我希望能够:

  • 在引导应用程序时添加脚本
  • 不要从一个组件做,因为它不觉得这是任何组件的责任
  • 由于与组件相同的原因,不能从指令中执行
  • 不要从服务中进行,因为除非存在与现有服务相关的某种繁重逻辑,否则这不属于 IMO 服务
  • 避免在模块中进行。 一个模块可能没问题,但它不像使用 DI 那样灵活,而且由于 Angular 15 个独立组件是稳定的,所以为什么要费心使用一个模块

也就是说,为了在应用程序启动之前就做到这一点,这有点棘手。 因为我们在那个阶段没有可用的渲染器,而且我们无权访问包含elementRefnativeElement

所以这是我的看法:

export const YOUR_EXT_LIB_URL_TOKEN = new InjectionToken<string>('YOUR_EXT_LIB_URL_TOKEN');

export const YOUR_SETUP: Provider = {
  provide: APP_INITIALIZER,
  multi: true,
  useFactory: (
    doc: InjectionTokenType<typeof DOCUMENT>,
    rendererFactory: RendererFactory2,
    yourExternalLibToken: string,
  ) => {
    const renderer = rendererFactory.createRenderer(null, null);

    const script = renderer.createElement('script');
    script.type = 'text/javascript';
    script.src = yourExternalLibToken;
    renderer.appendChild(doc.body, script);

    return () => true;
  },
  deps: [DOCUMENT, RendererFactory2, YOUR_EXT_LIB_URL_TOKEN],
};

然后,您所要做的就是提供YOUR_EXT_LIB_URL_TOKEN并同时传递YOUR_SETUP提供商。

这样,一切都是通过 DI 注入的,非常灵活。 例如,您可以在共享库中提供YOUR_SETUP令牌,并在使用共享库的不同应用程序中提供YOUR_EXT_LIB_URL_TOKEN

我有这个模块,它将外部库与其他逻辑一起组成了组件,而没有将<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 {...}

我注意到ES6规范的import是静态的,并且是在TypeScript转译过程中而不是在运行时解决的。

无论如何使其可配置,以便从CDN或本地文件夹加载file.js? 如何告诉Angular 2动态加载脚本?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM