web-dev-qa-db-fra.com

Comment ajouter des scripts JS externes aux composants VueJS

Je dois utiliser deux scripts externes pour les passerelles de paiement. À l'heure actuelle, les deux sont placés dans le fichier 'index.html'. Cependant, je ne veux pas charger ces fichiers au début. La passerelle de paiement est nécessaire uniquement lorsque l'utilisateur ouvre un composant spécifique (à l'aide de router-view). Y'a-t-il une quelconque façon de réussir cela?

76
Gijo Varghese

Un moyen simple et efficace de résoudre ce problème consiste à ajouter votre script externe dans la vue mounted() de votre composant. Je vais vous illustrer par le script 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>

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

125
mejiamanuel57

en utilisant webpack et vue loader, vous pouvez faire quelque chose comme ceci

il attend que le script externe soit chargé avant de créer le composant, de sorte que les variables globar, etc., sont disponibles dans le composant

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)
  })
 }
},
15
mons droid

J'ai téléchargé un modèle HTML fourni avec les fichiers js personnalisés et jquery. Je devais attacher ces js à mon application. et continuez avec Vue.

Trouvé ce plugin, c'est un moyen simple d'ajouter des scripts externes à la fois via CDN et à partir de fichiers statiques 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")
11
PJ3

Utilisez-vous l’un des modèles de départ Webpack pour vue ( https://github.com/vuejs-templates/webpack )? Il est déjà configuré avec vue-loader ( https://github.com/vuejs/vue-loader ). Si vous n'utilisez pas de modèle de départ, vous devez configurer webpack et vue-loader.

Vous pouvez ensuite import vos scripts dans les composants appropriés (fichier unique). Avant cela, vous devez export parmi vos scripts ce que vous voulez import à vos composants.

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

~ Modifier ~
Vous pouvez importer à partir de ces wrappers:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-Paypal-checkout

5
ba_ul

Vous pouvez utiliser le paquetage vue-head pour ajouter des scripts et d’autres balises à l’en-tête de votre composant vue.

C'est aussi simple que:

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 },
      // ...
    ]
  }
})

Découvrez ceci lien pour plus d'exemples.

3
pamekar

Vous pouvez charger le script dont vous avez besoin avec une solution basée sur une promesse:

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) }

    }
  }
}

Veuillez noter que this.$root est un petit hacky et que vous devriez plutôt utiliser une solution vuex ou eventHub pour les événements globaux.

Vous feriez de ce qui précède un composant et l'utilisez où vous le souhaitez, il ne chargera le script que s'il est utilisé.

3
hitautodestruct

Vous pouvez utiliser vue-loader et coder vos composants dans leurs propres fichiers (composants à fichier unique). Cela vous permettra d'inclure des scripts et des CSS sur une base de composant.

1
Daniel D

Pour garder des composants propres, vous pouvez utiliser mixins.

Sur votre composant, importez un fichier de mixage externe.

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 (j'inclus ceci, le cas échéant bloqué à l'importation)

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

La première réponse de create tag in monté est bonne, mais elle pose quelques problèmes:

Si vous modifiez votre lien plusieurs fois, il répète inlassablement la création de la balise.

J'ai donc créé un script pour résoudre ce problème, et vous pouvez supprimer la balise si vous le souhaitez.

C'est très simple, mais vous pouvez économiser du temps pour le créer vous-même.

// 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,
}

Et vous pouvez l'utiliser comme ceci:

// 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>

......
0
oraant