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

Ember中g-recaptcha组件刷新路由后无法渲染问题求助

解决Ember g-recaptcha组件刷新/直接访问路由时无法渲染的问题

我之前也遇到过完全一样的Ember reCAPTCHA组件问题,咱们来拆解一下原因和解决方案:

问题核心原因

当你直接刷新路由或者首次访问路由时,Google reCAPTCHA的异步脚本还没加载完成,你的组件就已经尝试调用window.grecaptcha.render方法了——这就是控制台报错Uncaught TypeError: window.grecaptcha.render is not a function的根源。而通过{{#link-to}}跳转时,脚本已经在之前的页面加载完毕,所以组件能正常初始化和渲染。

具体解决方案

1. 在路由层面提前加载reCAPTCHA脚本

最稳妥的方式是在进入目标路由前,确保脚本已经加载完成。可以在路由的beforeModel钩子中添加脚本加载逻辑:

// app/routes/your-target-route.js
import Route from '@ember/routing/route';

export default class YourTargetRoute extends Route {
  async beforeModel() {
    // 等待reCAPTCHA脚本加载完成再进入路由
    await this._loadRecaptchaScript();
  }

  _loadRecaptchaScript() {
    return new Promise((resolve, reject) => {
      // 如果脚本已经加载,直接resolve
      if (window.grecaptcha) {
        resolve();
        return;
      }

      const script = document.createElement('script');
      // 替换成你的sitekey,或者保持explicit模式
      script.src = 'https://www.google.com/recaptcha/api.js?render=explicit';
      script.async = true;
      script.defer = true;
      script.onload = resolve;
      script.onerror = () => reject(new Error('Failed to load reCAPTCHA script'));
      document.body.appendChild(script);
    });
  }
}

这样组件渲染时,window.grecaptcha肯定已经存在,不会出现找不到方法的错误。

2. 在组件内部添加加载检测逻辑

如果不想在路由层面处理,也可以在组件内部做延迟渲染,等待脚本加载完成:

// app/components/g-recaptcha.js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class GRecaptchaComponent extends Component {
  @tracked isRecaptchaReady = false;

  constructor() {
    super(...arguments);
    this._waitForRecaptcha();
  }

  _waitForRecaptcha() {
    // 立即检查一次
    if (window.grecaptcha) {
      this.isRecaptchaReady = true;
      this._renderCaptcha();
      return;
    }

    // 轮询检测脚本加载状态,间隔可以根据需要调整
    const checkInterval = setInterval(() => {
      if (window.grecaptcha) {
        clearInterval(checkInterval);
        this.isRecaptchaReady = true;
        this._renderCaptcha();
      }
    }, 150);
  }

  _renderCaptcha() {
    window.grecaptcha.render(this.element, {
      sitekey: this.args.sitekey,
      // 这里添加你的其他reCAPTCHA配置,比如theme、size等
    });
  }
}

然后在组件模板中,只有当脚本准备好后才渲染容器:

{{#if this.isRecaptchaReady}}
  <div class="g-recaptcha-container"></div>
{{/if}}

3. 排查组件渲染阻塞问题

从Ember Inspector看到组件未被渲染,大概率是脚本加载失败导致组件初始化抛出错误,进而被Ember的错误处理机制阻止渲染。解决脚本加载时机后,这个问题应该会自动消失。另外可以检查组件模板中有没有条件渲染逻辑(比如{{#if}})意外阻止了组件显示。

内容的提问来源于stack exchange,提问作者El Poisen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:02:12