我想在安装Vue.js组件后渲染recaptcha.它可以正常加载和重新加载,但当我导航到另一个url并单击浏览器后退按钮时,它会抛出一个错误.

以下是我的设置:

  • 我正在页面底部加载api个脚本:

    <script src='https://www.google.com/recaptcha/api.js' async></script>

  • 在该页面上,我呈现了一个名为Contact.vue的全局注册组件,其中包含一个名为Recaptcha.vue的本地组件:

    <app-recaptcha @recaptchaResponse="updateRecaptchaResponse"></app-recaptcha>

Recaptcha.vue的代码如下所示:

<template>
    <div id="app-recaptcha">
        <div :id="placeholderId"></div>
    </div>
</template>


<script>
    export default {
        data() {
            return {
                sitekey: 'key_here',
                placeholderId: 'grecaptcha',
                widgetId: null
            }
        },


        mounted() {
            this.$nextTick(function () {
                this.render();
            });
        },


        methods: {
            render() {
                this.widgetId = window.grecaptcha.render(this.placeholderId, {
                    sitekey: this.sitekey,
                    callback: (response) => {
                        this.$emit('recaptchaResponse', response);
                    }
                });
            },

            reset() {
                window.grecaptcha.reset(this.widgetId);
            }
        }
    }
</script>


<style>...</style>

在正常页面上,正常执行加载/重新加载this.render().然而,当我导航到另一个url并通过后退按钮返回时,我得到:Error in nextTick: "TypeError: window.grecaptcha.render is not a function".

我试图:

  • api脚本的onload事件上设置一个变量:

    <script src='...' onload="window.script = { recaptcha: 'ready' }" async></script>

  • 然后将其作为属性添加到Recaptcha.vue中的data():

    ready: window.script.recaptcha

  • 接下来,我在ready属性上添加了一个观察者,并在该观察者中try 运行this.render()

没有成功,错误仍然存在.我认为,即使在正常的加载/重新加载情况下,我也只是"幸运地"在安装组件之前加载了api个脚本,而在mounted()钩子中放置this.render()也没有帮助.

你知道我怎样才能告诉Recaptcha.vue外部脚本已经加载完毕,然后才渲染recaptcha吗?

推荐答案

好的,这里有一个理论:添加数据属性

captchaReady: false, 
checkingInterval: null,

创建

let localThis = this 
this.checkingInterval = setInterval(function(){
  if (window.grecaptcha) {
    localThis.captchaReady = true
  }
}, 500) //or whatever interval you want to check 

然后

watch: {
  captchaReady: function(data) {
    if (data) { 
       clearInterval(this.checkingInterval) 
       this.render()
    }
  }
}

Vue.js相关问答推荐

通过另一个文件调用模块化窗口组件

检测Vue3/Vue-test-utils中的Vuex还原/Mutations

虚拟DOM在Vue中姗姗来迟

带 Bootstrap 的 Vue js,导航栏菜单不起作用

无法在cPanel/SSH上构建 | Laravel + Vue优化

如何使用 Vite 从公共目录导入 JSON 文件?

Nuxt 和 Vite 有什么区别?

在 vuejs 中的图像中包含 router-link 标记

在基于 TypeScript 的 Vue 中将 vuex 状态和Mutations绑定到复选框组件属性

在 vue-router 中带有路由的 Vuejs2 模态

W3C 验证和 Vue 的 HTML 绑定语法

Transition-group children must be keyed...but they are keyed

如何在 Vue 中转发 $refs

Vuejs:我应该在 vue-router SPA 中的哪里放置一些常用的 js 工具?

Vue 组件中的组件渲染函数中可能存在无限更新循环警告

如何从 vue 组件调用 App.vue 中的方法

如何在 Promise 回调中更新 Vue 应用程序或组件的属性?

偶数行格式化

Vue 2.0 设置路由 - 不要使用new来产生副作用

Vue Cli 3:定义的输出路径