Skip to content

Commit 14cf23c

Browse files
committed
- Refactored the Vue component to load a lot faster (not using intervals anymore)
- Made it possible to bind the response token to a model, the Vue way. <google-recaptcha-v3 v-model="yourDataAttribute"></google-recaptcha-v3> - Made all props optional with default values that can be configured on the component
1 parent 48b57f9 commit 14cf23c

File tree

1 file changed

+42
-56
lines changed

1 file changed

+42
-56
lines changed

vuejs/GoogleReCaptchaV3.vue

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,74 @@
11
<template>
2-
<div :id="elementId"
3-
></div>
2+
<div :id="id"></div>
43
</template>
54

65
<script>
76
export default {
87
name: 'google-recaptcha-v3',
98
props: {
10-
siteKey: {
9+
action: {
1110
type: String,
12-
required: true
11+
required: false,
12+
default: 'validate_grecaptcha'
1313
},
14-
elementId: {
14+
id: {
1515
type: String,
16-
required: true
16+
required: false,
17+
default: 'grecaptcha_container'
18+
},
19+
siteKey: {
20+
type: String,
21+
required: false, // set to true if you don't want to store the siteKey in this component
22+
default: '' // set siteKey here if you want to store it in this component
1723
},
1824
inline: {
1925
type: Boolean,
20-
default: false
26+
required: false,
27+
default: false,
2128
},
22-
action: {
23-
type: String,
24-
required: true
25-
}
2629
},
2730
data() {
2831
return {
29-
gAssignedId: null,
30-
captchaReady: false,
31-
renderedReady: false,
32-
checkInterval: null,
33-
checkIntervalRunCount: 0
32+
captchaId: null,
3433
}
3534
},
36-
created() {
37-
},
38-
computed: {},
3935
mounted() {
4036
this.init();
4137
},
42-
watch: {
43-
captchaReady: function (data) {
44-
if (data) {
45-
clearInterval(this.checkInterval)
46-
this.render()
47-
}
48-
},
49-
renderedReady: function (data) {
50-
if (data) {
51-
clearInterval(this.checkInterval)
52-
this.execute()
53-
}
54-
},
55-
},
5638
methods: {
57-
execute() {
58-
let action = this.action;
59-
window.grecaptcha.ready(function () {
60-
grecaptcha.execute(this.gAssignedId, {
61-
action: action
62-
});
63-
});
39+
init() {
40+
if (!('grecaptcha' in window)) {
41+
42+
window.gRecaptchaOnLoad = this.render;
43+
44+
let recaptchaScript = document.createElement('script');
45+
recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js?render=explicit&onload=gRecaptchaOnLoad');
46+
recaptchaScript.async = true;
47+
recaptchaScript.defer = true;
48+
document.head.appendChild(recaptchaScript);
49+
50+
} else {
51+
this.render();
52+
}
6453
},
54+
6555
render() {
66-
this.gAssignedId = window.grecaptcha.render(this.elementId, {
56+
this.captchaId = window.grecaptcha.render(this.id, {
6757
sitekey: this.siteKey,
6858
badge: this.inline === true ? 'inline' : '',
69-
size: 'invisible'
59+
size: 'invisible',
60+
'expired-callback': this.execute
7061
});
71-
this.renderedReady = true;
62+
63+
this.execute();
7264
},
73-
init() {
74-
this.checkInterval = setInterval(() => {
75-
this.checkIntervalRunCount++;
76-
if (window.grecaptcha && window.grecaptcha.hasOwnProperty('render')) {
77-
this.captchaReady = true
78-
} else {
79-
let recaptchaScript = document.createElement('script');
80-
recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js?render=explicit');
81-
document.head.appendChild(recaptchaScript);
82-
recaptchaScript.async = true;
83-
recaptchaScript.defer = true;
84-
}
85-
}, 1000)
65+
66+
execute() {
67+
window.grecaptcha.execute(this.captchaId, {
68+
action: this.action,
69+
}).then((token) => {
70+
this.$emit('input', token);
71+
});
8672
}
8773
}
8874
}

0 commit comments

Comments
 (0)