Come aggiungere script JS esterni ai componenti VueJS


151

Devo usare due script esterni per i gateway di pagamento. In questo momento entrambi sono inseriti nel index.htmlfile. Tuttavia, non voglio caricare questi file all'inizio stesso. Il gateway di pagamento è necessario solo quando l'utente apre un componente specifico ( using router-view).

Esiste un modo per raggiungere questo obiettivo?


Puoi usarlo /public/index.htmlper farlo?
user3290525,

Risposte:


240

Un modo semplice ed efficace per risolvere questo problema è aggiungendo lo script esterno alla versione mounted()del componente. Ti illustrerò con lo script di Google Recaptcha :

<template>
   .... your HTML
</template>

<script>
  export default {
    data: () => ({
      ......data of your component
    }),
    mounted() {
      let recaptchaScript = document.createElement('script')
      recaptchaScript.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
      document.head.appendChild(recaptchaScript)
    },
    methods: {
      ......methods of your component
    }
  }
</script>

Fonte: https://medium.com/@lassiuosukainen/how-to-include-a-script-tag-on-a-vue-component-fe10940af9e8


22
created()non è possibile ottenere il documento, utilizzare mounted()invece
Barlas Apaydin

15
Aggiungi recaptchaScript.async = trueprima di aggiungerlo alla testa.
Joe Eifert,

6
recaptchaScript.defer = truepuò anche essere adatto a qualcuno
Tarasovych,

3
questa è sicuramente la risposta migliore poiché vue è inteso come un framework di componenti a file singolo. a meno che il file compnent corrente sia estremamente grande, suggerirei di aggiungere la funzione alle sezioni montate () e / o beforeMount () dei tag di script ... vedere la funzionalità beforeMount () prima di decidere vuejs.org/v2/api/#beforeMount
Kyle Joeckel,

1
@KeisukeNagakawa teoricamente, sì. Vedi questa risposta stackoverflow.com/questions/1605899/…
Jeff Ryan il

28

Ho scaricato alcuni template HTML forniti con file js e jquery personalizzati. Ho dovuto collegare quelle js alla mia app. e continua con Vue.

Trovato questo plugin, è un modo semplice per aggiungere script esterni sia tramite CDN che da file statici https://www.npmjs.com/package/vue-plugin-load-script

// local files
// you have to put your scripts into the public folder. 
// that way webpack simply copy these files as it is.
Vue.loadScript("/js/jquery-2.2.4.min.js")

// cdn
Vue.loadScript("https://maps.googleapis.com/maps/api/js")

Questo è un modo davvero semplice e accurato per farlo. Mi piace questo metodo
Vixson

25

usando webpack e vue loader puoi fare qualcosa del genere

attende che venga caricato lo script esterno prima di creare il componente, quindi nel componente sono disponibili var. globar ecc

components: {
 SomeComponent: () => {
  return new Promise((resolve, reject) => {
   let script = document.createElement('script')
   script.onload = () => {
    resolve(import(someComponent))
   }
   script.async = true
   script.src = 'https://maps.googleapis.com/maps/api/js?key=APIKEY&libraries=places'
   document.head.appendChild(script)
  })
 }
},

L'ho usato su montato
Oranit Dar

>> "Dove si inserisce questo codice?" : È nella sezione componenti del componente vuejs.
ADM-IT

7

Stai utilizzando uno dei modelli di avvio Webpack per vue ( https://github.com/vuejs-templates/webpack )? Viene già configurato con vue-loader ( https://github.com/vuejs/vue-loader ). Se non stai utilizzando un modello iniziale, devi configurare webpack e vue-loader.

È quindi possibile importgli script per i componenti pertinenti (file singolo). Prima di ciò, devi exportdai tuoi script ciò che vuoi importai tuoi componenti.

Importazione ES6:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
- http://exploringjs.com/es6/ch_modules.html

~ Modifica ~
È possibile importare da questi wrapper:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout


2
Questi script provengono da paypal e stripe. Non riesco a scaricare il file messo localmente
Gijo Varghese,


risposta scadente ... dare una spiegazione sul perché è richiesto Vue Loader
Kyle Joeckel,

6

È possibile utilizzare il pacchetto vue-head per aggiungere script e altri tag all'inizio del componente vue.

È semplice come:

var myComponent = Vue.extend({
  data: function () {
    return {
      ...
    }
  },
  head: {
    title: {
      inner: 'It will be a pleasure'
    },
    // Meta tags
    meta: [
      { name: 'application-name', content: 'Name of my application' },
      { name: 'description', content: 'A description of the page', id: 'desc' }, // id to replace intead of create element
      // ...
      // Twitter
      { name: 'twitter:title', content: 'Content Title' },
      // with shorthand
      { n: 'twitter:description', c: 'Content description less than 200 characters'},
      // ...
      // Google+ / Schema.org
      { itemprop: 'name', content: 'Content Title' },
      { itemprop: 'description', content: 'Content Title' },
      // ...
      // Facebook / Open Graph
      { property: 'fb:app_id', content: '123456789' },
      { property: 'og:title', content: 'Content Title' },
      // with shorthand
      { p: 'og:image', c: 'https://example.com/image.jpg' },
      // ...
    ],
    // link tags
    link: [
      { rel: 'canonical', href: 'http://example.com/#!/contact/', id: 'canonical' },
      { rel: 'author', href: 'author', undo: false }, // undo property - not to remove the element
      { rel: 'icon', href: require('./path/to/icon-16.png'), sizes: '16x16', type: 'image/png' }, 
      // with shorthand
      { r: 'icon', h: 'path/to/icon-32.png', sz: '32x32', t: 'image/png' },
      // ...
    ],
    script: [
      { type: 'text/javascript', src: 'cdn/to/script.js', async: true, body: true}, // Insert in body
      // with shorthand
      { t: 'application/ld+json', i: '{ "@context": "http://schema.org" }' },
      // ...
    ],
    style: [
      { type: 'text/css', inner: 'body { background-color: #000; color: #fff}', undo: false },
      // ...
    ]
  }
})

Dai un'occhiata a questo link per altri esempi.


qual è il vantaggio o la differenza rispetto all'uso di Vuex Store?
Kyle Joeckel,

6

Se si sta tentando di incorporare script js esterni nel modello del componente vue.js, seguire le istruzioni seguenti:

Volevo aggiungere un codice di incorporamento javascript esterno al mio componente in questo modo:

<template>
  <div>
    This is my component
    <script src="https://badge.dimensions.ai/badge.js"></script>
  </div>
<template>

E Vue mi ha mostrato questo errore:

I modelli dovrebbero essere responsabili solo della mappatura dello stato sull'interfaccia utente. Evita di inserire tag con effetti collaterali nei tuoi modelli, ad esempio perché non verranno analizzati.


Il modo in cui l'ho risolto è stato aggiungendotype="application/javascript" ( vedi questa domanda per saperne di più sul tipo MIME per js ):

<script type="application/javascript" defer src="..."></script>


È possibile notare l' deferattributo. Se vuoi saperne di più guarda questo video di Kyle


4

Puoi caricare lo script di cui hai bisogno con una soluzione basata sulla promessa:

export default {
  data () {
    return { is_script_loading: false }
  },
  created () {
    // If another component is already loading the script
    this.$root.$on('loading_script', e => { this.is_script_loading = true })
  },
  methods: {
    load_script () {
      let self = this
      return new Promise((resolve, reject) => {

        // if script is already loading via another component
        if ( self.is_script_loading ){
          // Resolve when the other component has loaded the script
          this.$root.$on('script_loaded', resolve)
          return
        }

        let script = document.createElement('script')
        script.setAttribute('src', 'https://www.google.com/recaptcha/api.js')
        script.async = true

        this.$root.$emit('loading_script')

        script.onload = () => {
          /* emit to global event bus to inform other components
           * we are already loading the script */
          this.$root.$emit('script_loaded')
          resolve()
        }

        document.head.appendChild(script)

      })

    },

    async use_script () {
      try {
        await this.load_script()
        // .. do what you want after script has loaded
      } catch (err) { console.log(err) }

    }
  }
}

Nota che this.$rootè un po 'confuso e dovresti usare invece una soluzione vuex o eventHub per gli eventi globali.

Trasformeresti quanto sopra in un componente e lo utilizzeresti dove necessario, caricherà lo script solo quando usato.


3

Questo può essere fatto semplicemente in questo modo.

  created() {
    var scripts = [
      "https://cloudfront.net/js/jquery-3.4.1.min.js",
      "js/local.js"
    ];
    scripts.forEach(script => {
      let tag = document.createElement("script");
      tag.setAttribute("src", script);
      document.head.appendChild(tag);
    });
  }

2

Per mantenere componenti puliti è possibile utilizzare i mixin.

Sul tuo componente importa il file mixin esterno.

Profile.vue

import externalJs from '@client/mixins/externalJs';

export default{
  mounted(){
    this.externalJsFiles();
  }
}

externalJS.js

import('@JSassets/js/file-upload.js').then(mod => {
  // your JS elements 
})

babelrc (includo questo, se qualcuno rimane bloccato durante l'importazione)

{
  "presets":["@babel/preset-env"],
  "plugins":[
    [
     "module-resolver", {
       "root": ["./"],
       alias : {
         "@client": "./client",
         "@JSassets": "./server/public",
       }
     }
    ]
}

2

La risposta migliore di create tag in montata è buona, ma presenta alcuni problemi: se cambi il link più volte, ripeterà ripetutamente la creazione di tag.

Quindi ho creato uno script per risolvere questo problema e, se lo desideri, puoi eliminare il tag.

È molto semplice, ma può farti risparmiare tempo per crearlo da solo.

// PROJECT/src/assets/external.js

function head_script(src) {
    if(document.querySelector("script[src='" + src + "']")){ return; }
    let script = document.createElement('script');
    script.setAttribute('src', src);
    script.setAttribute('type', 'text/javascript');
    document.head.appendChild(script)
}

function body_script(src) {
    if(document.querySelector("script[src='" + src + "']")){ return; }
    let script = document.createElement('script');
    script.setAttribute('src', src);
    script.setAttribute('type', 'text/javascript');
    document.body.appendChild(script)
}

function del_script(src) {
    let el = document.querySelector("script[src='" + src + "']");
    if(el){ el.remove(); }
}


function head_link(href) {
    if(document.querySelector("link[href='" + href + "']")){ return; }
    let link = document.createElement('link');
    link.setAttribute('href', href);
    link.setAttribute('rel', "stylesheet");
    link.setAttribute('type', "text/css");
    document.head.appendChild(link)
}

function body_link(href) {
    if(document.querySelector("link[href='" + href + "']")){ return; }
    let link = document.createElement('link');
    link.setAttribute('href', href);
    link.setAttribute('rel', "stylesheet");
    link.setAttribute('type', "text/css");
    document.body.appendChild(link)
}

function del_link(href) {
    let el = document.querySelector("link[href='" + href + "']");
    if(el){ el.remove(); }
}

export {
    head_script,
    body_script,
    del_script,
    head_link,
    body_link,
    del_link,
}

E puoi usarlo in questo modo:

// PROJECT/src/views/xxxxxxxxx.vue

......

<script>
    import * as external from '@/assets/external.js'
    export default {
        name: "xxxxxxxxx",
        mounted(){
            external.head_script('/assets/script1.js');
            external.body_script('/assets/script2.js');
            external.head_link('/assets/style1.css');
            external.body_link('/assets/style2.css');
        },
        destroyed(){
            external.del_script('/assets/script1.js');
            external.del_script('/assets/script2.js');
            external.del_link('/assets/style1.css');
            external.del_link('/assets/style2.css');
        },
    }
</script>

......

2
Una volta caricato, uno script è già in memoria. Rimuovendolo dal dom non si rimuove la sua impronta.
Danbar

1

È possibile utilizzare vue-loader e codificare i componenti nei propri file (componenti a file singolo). Ciò ti consentirà di includere script e CSS su una base componente.


4
Questi script provengono da paypal e stripe. Non riesco a scaricare il file messo localmente
Gijo Varghese,

1
il collegamento è interrotto
Roberto,

Puoi scaricare gli script esterni, visualizzare l'origine, copiare / incollare nel tuo file.
minimallinux,

1
@minimallinux Nel caso di Stripe e Paypal, ciò violerà PCI-DSS. Quindi non farlo.
Duncan Jones,

0

La soluzione più semplice è aggiungere lo script nel index.htmlfile del tuo progetto vue

index.html:

 <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <title>vue-webpack</title>
      </head>
      <body>
        <div id="app"></div>
        <!-- start Mixpanel --><script type="text/javascript">(function(c,a){if(!a.__SV){var b=window;try{var d,m,j,k=b.location,f=k.hash;d=function(a,b){return(m=a.match(RegExp(b+"=([^&]*)")))?m[1]:null};f&&d(f,"state")&&(j=JSON.parse(decodeURIComponent(d(f,"state"))),"mpeditor"===j.action&&(b.sessionStorage.setItem("_mpcehash",f),history.replaceState(j.desiredHash||"",c.title,k.pathname+k.search)))}catch(n){}var l,h;window.mixpanel=a;a._i=[];a.init=function(b,d,g){function c(b,i){var a=i.split(".");2==a.length&&(b=b[a[0]],i=a[1]);b[i]=function(){b.push([i].concat(Array.prototype.slice.call(arguments,
    0)))}}var e=a;"undefined"!==typeof g?e=a[g]=[]:g="mixpanel";e.people=e.people||[];e.toString=function(b){var a="mixpanel";"mixpanel"!==g&&(a+="."+g);b||(a+=" (stub)");return a};e.people.toString=function(){return e.toString(1)+".people (stub)"};l="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" ");
    for(h=0;h<l.length;h++)c(e,l[h]);var f="set set_once union unset remove delete".split(" ");e.get_group=function(){function a(c){b[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));e.push([d,call2])}}for(var b={},d=["get_group"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<f.length;c++)a(f[c]);return b};a._i.push([b,d,g])};a.__SV=1.2;b=c.createElement("script");b.type="text/javascript";b.async=!0;b.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?
    MIXPANEL_CUSTOM_LIB_URL:"file:"===c.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";d=c.getElementsByTagName("script")[0];d.parentNode.insertBefore(b,d)}})(document,window.mixpanel||[]);
    mixpanel.init("xyz");</script><!-- end Mixpanel -->
        <script src="/dist/build.js"></script>
      </body>
    </html>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.