DEV Community

Cover image for Add An External Script to a Vue Component
SandraRodgers
SandraRodgers

Posted on

Add An External Script to a Vue Component

Yesterday I tweeted this question out to the world:

Only one person liked it. Maybe Twitter isn't the best forum for that question. Or maybe the character limit made it unclear what I meant. Or maybe I don't have enough followers for the tweet to get any traction....

I thought it was a good question though.

Here's the question worded more clearly:

How would you go about bringing in a script from a third-party into a Vue component? And then making sure the script is there before performing logic on something brought in by the script?

I was able to do this one way, but I'm curious if there are other approaches.

Here's an example scenario and my solution.

Scenario: Load Google Recaptcha API and Perform Action if API has Loaded

This is an example for the sake of showing how to do this, but it could be applied to anytime you need to load a JS script into your component and wait until after it has loaded to perform some action.

The example is a Recaptcha checkmark to verify that the user is not a robot.

Recaptcha Checkmark

Step 1: Load the Script in the setup function

First, create a script element using Vanilla JS document.createElement and setAttribute with "src" set to the script source url. Then use appendChild to append that element do the document head.:

export default {

  setup() {
    const recaptchaScript = document.createElement("script");
    recaptchaScript.setAttribute(
      "src",
      "https://www.google.com/recaptcha/api.js"
    );
    document.head.appendChild(recaptchaScript);
}
Enter fullscreen mode Exit fullscreen mode

In Vue 3, the setup function runs before anything else, so we can create the script element at the very start of the component lifecycle. That ensures the script is there as soon as possible.

In Vue 2, this would be equivalent to building out the script element in the create lifecycle hook. There is a stack overflow question that shows how to do this in Vue 2.

Step 2: Use setInterval to check that the script has fully loaded

Create a variable to keep track of the state of the script being loaded. Set it to false to start.

let recaptchaScriptIsReady = false;
Enter fullscreen mode Exit fullscreen mode

Write a function using setInterval to continuously run, checking that the script is loaded:

 let checkInterval = setInterval(function () {
      if (grecaptcha) {
        recaptchaScriptIsReady = true;
        clearInterval(checkInterval);
        grecaptcha.ready(function () {
          grecaptcha.render("g-recaptcha", {
            sitekey: "YOUR API KEY",
          });
        });
      }
      return recaptchaScriptIsReady;
    }, 500);
Enter fullscreen mode Exit fullscreen mode

Notice that inside the function, the clearInterval takes in the named function checkInterval, which stops the setInterval from continuing to run. Here's the line of code I'm talking about:

 clearInterval(checkInterval);
Enter fullscreen mode Exit fullscreen mode

So basically, to solve this problem, I create the variable recaptchaScriptIsReady to track the state of the script that is loading, then use the if-check to make sure the script is now there, set the recaptchaScriptIsReady to true which now opens the gate to allowing the next part of the code to run, the code that is dependent upon the original script being loaded.

Do you have a different way to do this? I would be really interested to know! Please tell me in the comments!

And please follow me on Twitter! I hope this post was helpful to someone.

Recaptcha resource: https://developers.google.com/recaptcha

Top comments (6)

Collapse
 
alizangiabadicode profile image
Ali Zangiabadi

checkout vue-meta package. you can specify script and give it a callback.

Collapse
 
sandrarodgers profile image
SandraRodgers

I just took a look. Looks like an easy way to bring in a script to specific component. Thanks for the suggestion!

Collapse
 
t_pavard profile image
Tristan Pavard

Why not use onload ? demo

Collapse
 
sandrarodgers profile image
SandraRodgers

I didn't use onload because I'm still learning this stuff and I didn't think to use it. I know that there are better ways of doing this so I was hoping to get some ideas from people out there.

This is awesome, thanks!

Collapse
 
lagamura profile image
Lagaras Stelios

@t_pavard Thanks for the demo,

I am trying to replicate an issue in sfc vue playground
Is there any more convenient way for using packages there? I don't mind if it is cdn or npm.

Collapse
 
glzlyv profile image
Oscar Gonzalez Leyva

If I was to add content inside the script tag and not as an attribute, could I still use the onMounted() / setup method? Sorry if I'm wording it wrong.