You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular组件中加载外部JS文件(以Google Maps API为例)

我之前也碰到过不用angular-maps集成Google Maps的需求,下面几种方法亲测有效,你可以根据自己的场景选择:

方法一:组件内动态创建Script标签(按需加载)

如果只有单个组件需要用到地图,这种按需加载的方式最灵活,不会影响其他组件的加载速度。

步骤很简单:

  • 先在组件里定义地图初始化的方法
  • 在ngOnInit里动态生成script标签,配置好Google Maps的API地址和回调
  • 把组件的初始化方法挂载到window上(因为Google Maps的回调要求是全局函数)
  • 加个判断避免重复加载脚本

代码示例:

import { Component, OnInit } from '@angular/core';
import { environment } from '../../environments/environment';

// 扩展window接口,避免TypeScript报错
declare global {
  interface Window {
    initMap: () => void;
  }
}

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
  map: google.maps.Map | undefined;

  ngOnInit(): void {
    // 检查是否已加载过Google Maps脚本
    if (!document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]')) {
      const script = document.createElement('script');
      // 用环境变量存API Key,别硬编码!
      script.src = `https://maps.googleapis.com/maps/api/js?key=${environment.googleMapsApiKey}&callback=initMap`;
      script.async = true;
      script.defer = true;
      document.head.appendChild(script);
    }

    // 将组件的initMap绑定到全局window对象
    window.initMap = () => this.initMap();
  }

  // 实际的地图初始化逻辑
  initMap(): void {
    const mapContainer = document.getElementById('map') as HTMLElement;
    this.map = new google.maps.Map(mapContainer, {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8,
    });
  }
}
方法二:用Angular Renderer2创建Script标签(更规范)

如果想遵循Angular的最佳实践,避免直接操作DOM,可以用Renderer2来创建和添加script标签,它是Angular官方推荐的DOM操作方式。

代码示例:

import { Component, OnInit, Renderer2, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { environment } from '../../environments/environment';

declare global {
  interface Window {
    initMap: () => void;
  }
}

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
  map: google.maps.Map | undefined;

  constructor(
    private renderer: Renderer2,
    @Inject(DOCUMENT) private document: Document
  ) {}

  ngOnInit(): void {
    const existingScript = this.document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]');
    if (!existingScript) {
      const script = this.renderer.createElement('script');
      script.src = `https://maps.googleapis.com/maps/api/js?key=${environment.googleMapsApiKey}&callback=initMap`;
      script.async = true;
      script.defer = true;
      this.renderer.appendChild(this.document.head, script);
    }

    window.initMap = () => this.initMap();
  }

  initMap(): void {
    const mapContainer = this.document.getElementById('map') as HTMLElement;
    this.map = new google.maps.Map(mapContainer, {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8,
    });
  }
}
方法三:用APP_INITIALIZER全局预加载

如果你的应用多个组件都需要用到Google Maps,那可以在应用启动时就把脚本加载好,这样所有组件都能直接使用,不用每个组件都处理加载逻辑。

第一步:创建加载服务

先写一个服务来封装地图脚本的加载逻辑:

import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { environment } from '../../environments/environment';

@Injectable({
  providedIn: 'root'
})
export class GoogleMapsLoaderService {
  constructor(@Inject(DOCUMENT) private document: Document) {}

  load(): Promise<void> {
    return new Promise((resolve, reject) => {
      const existingScript = this.document.querySelector('script[src*="maps.googleapis.com/maps/api/js"]');
      if (existingScript) {
        resolve();
        return;
      }

      const script = this.document.createElement('script');
      script.src = `https://maps.googleapis.com/maps/api/js?key=${environment.googleMapsApiKey}`;
      script.async = true;
      script.defer = true;

      // 加载成功和失败的回调
      script.onload = () => resolve();
      script.onerror = () => reject(new Error('Google Maps API加载失败'));

      this.document.head.appendChild(script);
    });
  }
}

第二步:在AppModule中配置初始化器

修改app.module.ts,用APP_INITIALIZER让应用启动时先加载地图脚本:

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { GoogleMapsLoaderService } from './services/google-maps-loader.service';

// 初始化工厂函数
export function initializeGoogleMaps(loader: GoogleMapsLoaderService) {
  return () => loader.load();
}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: initializeGoogleMaps,
      deps: [GoogleMapsLoaderService],
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

第三步:组件中直接使用

现在组件里不用再处理加载,直接写初始化逻辑就行:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
  map: google.maps.Map | undefined;

  ngOnInit(): void {
    this.initMap();
  }

  initMap(): void {
    const mapContainer = document.getElementById('map') as HTMLElement;
    this.map = new google.maps.Map(mapContainer, {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8,
    });
  }
}

额外注意事项

  1. API Key管理:一定要用Angular的环境变量(environment.ts和environment.prod.ts)来存储API Key,不要直接写在代码里,避免泄露。
  2. TypeScript类型提示:安装@types/google.maps包(npm install @types/google.maps --save-dev),这样就能获得Google Maps API的类型提示,开发更顺畅。
  3. 错误处理:动态加载时记得加上onerror回调,处理脚本加载失败的情况,比如给用户提示。

内容的提问来源于stack exchange,提问作者Hamid Asghari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:39:54