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

Angular 18集成Google Maps与ReCaptcha如何符合GDPR Cookie合规?

Angular 18 + Google Maps/ReCaptcha 欧盟Cookie合规实现方案

欧盟Cookie法规核心要求:非必要第三方Cookie(如Google Maps、ReCaptcha产生的跟踪/功能Cookie)必须获得用户明确同意后才能加载。以下是针对Angular18的落地实现方案:

1. 实现Cookie同意管理组件

先做一个基础的同意弹窗,支持用户选择是否允许第三方服务的Cookie,将选择结果持久化到localStorage。

<div class="cookie-consent-overlay" *ngIf="showConsent">
  <div class="consent-modal">
    <h3>Cookie 设置</h3>
    <p>我们使用必要Cookie保障网站运行,第三方服务(Google Maps、ReCaptcha)需要您的同意才能加载对应的Cookie。</p>
    <div class="consent-options">
      <label><input type="checkbox" [(ngModel)]="acceptNecessary" disabled> 必要Cookie</label>
      <label><input type="checkbox" [(ngModel)]="acceptThirdParty"> 第三方服务Cookie(Maps/ReCaptcha)</label>
    </div>
    <div class="consent-actions">
      <button (click)="saveConsent()">保存设置</button>
      <button (click)="acceptAll()">全部同意</button>
    </div>
  </div>
</div>
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-cookie-consent',
  standalone: true,
  imports: [FormsModule],
  templateUrl: './cookie-consent.component.html',
  styleUrls: ['./cookie-consent.component.css']
})
export class CookieConsentComponent implements OnInit {
  showConsent = false;
  acceptNecessary = true;
  acceptThirdParty = false;

  ngOnInit(): void {
    // 检查是否已有同意记录
    const consent = localStorage.getItem('cookieConsent');
    if (!consent) {
      this.showConsent = true;
    }
  }

  saveConsent(): void {
    localStorage.setItem('cookieConsent', JSON.stringify({
      necessary: this.acceptNecessary,
      thirdParty: this.acceptThirdParty
    }));
    this.showConsent = false;
    // 触发同意变更事件,通知其他组件加载第三方服务
    window.dispatchEvent(new CustomEvent('cookieConsentUpdated'));
  }

  acceptAll(): void {
    this.acceptThirdParty = true;
    this.saveConsent();
  }
}

2. 动态加载Google Maps组件

不要在应用启动时直接导入Google Maps的依赖,而是等待用户同意后再动态加载脚本并初始化地图。

地图组件逻辑(google-maps.component.ts)

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

@Component({
  selector: 'app-google-maps',
  standalone: true,
  template: '<div #mapContainer style="width: 100%; height: 400px;"></div>'
})
export class GoogleMapsComponent implements OnInit {
  @ViewChild('mapContainer') mapContainer!: ElementRef<HTMLDivElement>;
  private map: google.maps.Map | undefined;

  ngOnInit(): void {
    // 监听同意变更事件
    window.addEventListener('cookieConsentUpdated', () => this.loadMap());
    // 页面加载时检查已有同意
    const consent = JSON.parse(localStorage.getItem('cookieConsent') || '{}');
    if (consent.thirdParty) {
      this.loadMap();
    }
  }

  private loadMap(): void {
    // 检查脚本是否已加载
    if (document.querySelector('script[src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"]')) {
      this.initMap();
      return;
    }
    // 动态加载Google Maps脚本
    const script = document.createElement('script');
    script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY';
    script.onload = () => this.initMap();
    document.body.appendChild(script);
  }

  private initMap(): void {
    this.map = new google.maps.Map(this.mapContainer.nativeElement, {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8
    });
  }
}

3. 控制Google ReCaptcha加载

同理,ReCaptcha脚本仅在用户同意后加载,可通过条件渲染+动态脚本注入实现。

ReCaptcha组件逻辑(recaptcha.component.ts)

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

@Component({
  selector: 'app-recaptcha',
  standalone: true,
  template: '<div #recaptchaContainer></div>'
})
export class RecaptchaComponent implements OnInit {
  @ViewChild('recaptchaContainer') recaptchaContainer!: ElementRef<HTMLDivElement>;

  ngOnInit(): void {
    window.addEventListener('cookieConsentUpdated', () => this.loadRecaptcha());
    const consent = JSON.parse(localStorage.getItem('cookieConsent') || '{}');
    if (consent.thirdParty) {
      this.loadRecaptcha();
    }
  }

  private loadRecaptcha(): void {
    if (document.querySelector('script[src="https://www.google.com/recaptcha/api.js"]')) {
      this.renderRecaptcha();
      return;
    }
    const script = document.createElement('script');
    script.src = 'https://www.google.com/recaptcha/api.js';
    script.onload = () => this.renderRecaptcha();
    document.body.appendChild(script);
  }

  private renderRecaptcha(): void {
    grecaptcha.render(this.recaptchaContainer.nativeElement, {
      sitekey: 'YOUR_RECAPTCHA_SITE_KEY',
      callback: (response: string) => {
        // 处理验证回调
      }
    });
  }
}

4. 合规补充措施

  • Cookie政策页面:明确列出Google Maps(如NID、SID)和ReCaptcha(如__Secure-1PAPISID、__Secure-1PSID)的Cookie类型、用途、有效期,以及用户修改同意设置的方法。
  • 全局同意检查:在app.component.ts中初始化时检查同意状态,若用户未同意,默认不加载任何第三方服务。
  • 静态地图 fallback:用户未同意前,显示Google静态地图图片(无需Cookie),点击后提示需要同意才能加载交互地图。

内容的提问来源于stack exchange,提问作者Mario Proietti

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 14:15:55