コンポーネントのvue.jsでrecaptchaコールバックを動作させようとしています。キャプチャ自体は機能しますが、data-callback
属性で定義したコールバックは機能しません。
考えられるすべてを試しましたが、ReCAPTCHA couldn't find user-provided function: dothisthat
エラーが引き続き発生します。
ここにコンポーネントがあります
<script>
function dothisthat (){
alert(312);
}
</script>
<template>
<div class="well main-well">
<h4>Captcha</h4>
<p class="small">You must complete the captcha to finish your booking.</p>
<div id="captcha-wrapper">
<div class="g-recaptcha" :data-sitekey="captchaKey" data-callback="dothisthat"></div>
</div>
</div>
</template>
<script>
function dothisthat (){
alert(123);
}
import * as filters from '../../../filters';
import Translation from '../../../Translation';
export default {
name: 'Captcha',
props: {
},
computed: {
captchaKey: function() {
return this.$store.getters.captcha;
}
},
methods: {
dothisthat: function(){
return function() {
console.log("123");
};
}
},
mounted(){
function dothisthat() {
alert(123);
}
$(function() {
function dothisthat() {
alert(123);
}
});
}
}
</script>
dothisthat
関数のいずれも呼び出されていません。私は何を間違えていますか?
私もこの問題に遭遇し、それを解決するのに2日かかりました。
そこで、将来的に同じ状況に陥る人々のための簡単なガイドとなるように、recaptchaをvue.jsと段階的にゼロから統合するための一般的な答えをここで提供します(ここではvue-cliが使用されていると思います)。
注:ここでは目に見えないrecaptchaを使用していますが、プロセスは通常のものとかなり似ています
ステップ1:
recaptcha javascript apiをindex.htmlに追加します
index.html
<script src="https://www.google.com/recaptcha/api.js" async defer></script>
ステップ2:
Recaptcha
と呼ばれるコンポーネントを作成します(コンポーネントを作成すると、コードが読みやすくなり、保守が容易になり、必要に応じてrecaptchaを複数のページに追加しやすくなります)
Recaptcha.vue
<template>
<div
id="g-recaptcha"
class="g-recaptcha"
:data-sitekey="sitekey">
</div>
</template>
<script>
export default {
data () {
return {
sitekey: '6LfAEj0UAAAAAFTGLqGozrRD8ayOy*********',
widgetId: 0
}
},
methods: {
execute () {
window.grecaptcha.execute(this.widgetId)
},
reset () {
window.grecaptcha.reset(this.widgetId)
},
render () {
if (window.grecaptcha) {
this.widgetId = window.grecaptcha.render('g-recaptcha', {
sitekey: this.sitekey,
size: 'invisible',
// the callback executed when the user solve the recaptcha
callback: (response) => {
// emit an event called verify with the response as payload
this.$emit('verify', response)
// reset the recaptcha widget so you can execute it again
this.reset()
}
})
}
}
},
mounted () {
// render the recaptcha widget when the component is mounted
this.render()
}
}
</script>
ステップ3:
Recaptchaコンポーネントをインポートして、ページ(親コンポーネント)に追加します。
page.vue
<template>
<div>
<h1>Parent component (your page)</h1>
<button @click="executeRecaptcha">execute recaptcha</button>
<!-- listen to verify event emited by the recaptcha component -->
<recaptcha ref="recaptcha" @verify="submit"></recaptcha>
</div>
</template>
<script>
import Recaptcha from 'recaptcha'
export default {
components: {
Recaptcha
},
methods: {
// send your recaptcha token to the server to verify it
submit (response) {
console.log(response)
},
// execute the recaptcha widget
executeRecaptcha () {
this.$refs.recaptcha.execute()
}
}
}
</script>
コンポーネントを使用していませんが、同じ問題があり、最終的には次のように解決します。
HTML
<div id="recaptcha" class="g-recaptcha"></div>
<button id="submit" @click="validate">Submit</button>
<script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
JS
// ...
mounted: function() {
this.initReCaptcha();
},
methods: {
initReCaptcha: function() {
var self = this;
setTimeout(function() {
if(typeof grecaptcha === 'undefined') {
self.initReCaptcha();
}
else {
grecaptcha.render('recaptcha', {
sitekey: 'SITE_KEY',
size: 'invisible',
badge: 'inline',
callback: self.submit
});
}
}, 100);
},
validate: function() {
// your validations...
// ...
grecaptcha.execute();
},
submit: function(token) {
console.log(token);
}
},
サーバー側で検証するためにrecaptchaの応答値のみを探している場合、単純な解決策は、recaptcha要素をフォームに配置し、submit event
のターゲット要素から応答値を取得することです。
<form class="container"
@submit="checkForm"
method="post"
>
... // other elements of your form
<div class="g-recaptcha" data-sitekey="your_site_key"></div>
<p>
<input class="button" type="submit" value="Submit">
</p>
</form>
そしてcheckForm
メソッドで:
methods : {
checkForm: function (event) {
recaptcha_response_value = event.target['g-recaptcha-response'].value
...
}
私が他のソリューションで抱えていた問題は、時々window.grecaptcha.render
ReCaptchaが完全にロードされていない場合。 ドキュメント に従ってそれを確認する唯一の方法は、onload
メソッドを使用することです。
以下のこの例は、私がそれをどのように使用したかです。もちろん、コールバックで何をするかをカスタマイズできます。
ReCaptcha.Vue:
<template>
<div ref="grecaptcha"></div>
</template>
<script>
export default {
props: ['sitekey'],
methods: {
loaded(){
window.grecaptcha.render(this.$refs.grecaptcha, {
sitekey: this.sitekey,
callback: (response) => {
this.$emit('input', response);
},
});
},
},
mounted(){
/**
* Set Recapchat loaded function
*/
window.ReCaptchaLoaded = this.loaded;
/**
* Set Recaptcha script in header
*/
var script = document.createElement('script');
script.src = 'https://www.google.com/recaptcha/api.js?onload=ReCaptchaLoaded&render=explicit';
document.head.appendChild(script);
}
}
</script>
使用法:
<ReCaptcha sitekey="KEY" v-model="fields.g_recaptcha_response.value" />
in Vue Component :
テンプレート内:html
<template>
<form @submit.prevent="onSubmit">
<div class="form-group row">
<label for="email" class="col-sm-4 col-form-label text-md-right">Email : </label>
<div class="col-md-6">
<input v-model="email" id="email" type="email" class="form-control" value="" required autofocus>
<span class="invalid-feedback" role="alert">
<strong></strong>
</span>
</div>
</div>
<div class="form-group row">
<label for="password" class="col-md-4 col-form-label text-md-right">
Password :
</label>
<div class="col-md-6">
<input v-model="password" id="password" type="password" class="form-control" required>
<span class="invalid-feedback" role="alert">
<strong></strong>
</span>
</div>
</div>
<div class="form-group row">
<div class="col-md-6 offset-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="remember" v-model="remember">
<label class="form-check-label" for="remember">
Remember me
</label>
<div id="recaptcha" class="g-recaptcha" data-sitekey="6LehfpsUAAAAAIf3hvWNrGvat8o4lypZh_p6snRH"></div>
</div>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<a href="" class="btn btn-danger">Login with google</a>
<button type="submit" class="btn btn-primary">
Login
</button>
<a class="btn btn-link" href="">
Forgot Your Password?
</a>
</div>
</div>
</form>
とjavascript:
<script>
import swal from 'sweetalert';
export default {
data(){
return {
email: '',
password: '',
remember: ''
}
},
mounted: function() {
this.initReCaptcha();
},
methods: {
onSubmit(event) {
let recaptcha_response_value = event.target['g-recaptcha-response'].value;
console.log(recaptcha_response_value);
let formData = new FormData();
formData.append('email' , this.email);
formData.append('password' , this.password);
formData.append('remember' , this.remember);
formData.append('g-recaptcha-response' , recaptcha_response_value);
axios.post('/login' , formData)
.then(
function(res){
swal('ورود شما موفقیت آمیز بود');
}
)
.catch(function(err){
swal('ایمیل یا کلمه عبور اشتباه است یا اینکه هنوز ثبت نام نکرده اید');
console.log(err);
});
}
}
}