So fügen Sie VueJS-Komponenten externe JS-Skripte hinzu

150

Ich muss zwei externe Skripte für die Zahlungsgateways verwenden. Im Moment werden beide in die index.htmlDatei aufgenommen. Ich möchte diese Dateien jedoch nicht am Anfang selbst laden. Das Zahlungsgateway wird nur benötigt, wenn der Benutzer eine bestimmte Komponente öffnet ( using router-view).

Gibt es überhaupt etwas zu erreichen?

Gijo Varghese
quelle
Kannst du es benutzen /public/index.html, um es zu tun?
user3290525

Antworten:

237

Eine einfache und effektive Möglichkeit, dies zu lösen, besteht darin, Ihr externes Skript in den Vue mounted()Ihrer Komponente einzufügen . Ich werde Sie mit dem Google Recaptcha- Skript veranschaulichen :

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

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

mejiamanuel57
quelle
Das ist großartig. Ich habe es noch nicht versucht. Aber ich bin sicher, es wird funktionieren
Gijo Varghese
22
created()Methode kann kein Dokument erhalten, verwenden Sie mounted()stattdessen
Barlas Apaydin
15
Fügen Sie hinzu, recaptchaScript.async = truebevor Sie es an den Kopf anhängen.
Joe Eifert
6
recaptchaScript.defer = truekann auch für jemanden geeignet sein
Tarasovych
3
Dies ist mit Sicherheit die beste Antwort, da vue ein Framework für einzelne Dateikomponenten sein soll. Sofern Ihre aktuelle Compnent-Datei nicht extrem groß ist, würde ich empfehlen, die Funktion zu Ihren gemounteten () und / oder beforeMount () - Abschnitten Ihrer Skript-Tags hinzuzufügen. Lesen Sie bitte die beforeMount () -Funktionalität, bevor Sie sich für vuejs.org/v2/api/#beforeMount
Kyle Joeckel
28

Ich habe eine HTML-Vorlage heruntergeladen, die mit benutzerdefinierten JS-Dateien und JQuery geliefert wird. Ich musste diese js an meine App anhängen. und weiter mit Vue.

Mit diesem Plugin können Sie externe Skripte sowohl über CDN als auch aus statischen Dateien https://www.npmjs.com/package/vue-plugin-load-script auf saubere Weise hinzufügen

// 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")
PJ3
quelle
Dies ist eine wirklich nette und einfache Möglichkeit, dies zu tun. Ich mag diese Methode
Vixson
25

Mit Webpack und Vue Loader können Sie so etwas tun

Es wartet, bis das externe Skript geladen ist, bevor die Komponente erstellt wird, sodass globale Variablen usw. in der Komponente verfügbar sind

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)
  })
 }
},
Mons Droide
quelle
Ich habe es in berittenen
Oranit Dar
>> "Wo platzieren Sie diesen Code?" : Es befindet sich im Komponentenbereich Ihrer vuejs-Komponente.
ADM-IT
7

Verwenden Sie eine der Webpack-Startervorlagen für vue ( https://github.com/vuejs-templates/webpack )? Es ist bereits mit vue-loader eingerichtet ( https://github.com/vuejs/vue-loader ). Wenn Sie keine Starter-Vorlage verwenden, müssen Sie Webpack und Vue-Loader einrichten.

Sie können dann importIhre Skripte zu den relevanten (Einzeldatei-) Komponenten. Vorher müssen Sie exportvon Ihren Skripten, was Sie wollen, importzu Ihren Komponenten.

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

~ Bearbeiten ~
Sie können aus diesen Wrappern importieren:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout

ba_ul
quelle
2
Diese Skripte sind von Paypal und Stripe. Ich kann die Datei nicht lokal herunterladen
Gijo Varghese
2
Lösen diese Wrapper Ihr Problem? github.com/matfish2/vue-stripe und github.com/khoanguyen96/vue-paypal-checkout
ba_ul
lahme Antwort ... erklären Sie, warum Vue Loader erforderlich ist
Kyle Joeckel
6

Mit dem vue-head- Paket können Sie dem Kopf Ihrer vue-Komponente Skripte und andere Tags hinzufügen.

Es ist so einfach wie:

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

Weitere Beispiele finden Sie unter diesem Link .

Pamekar
quelle
Was ist der Vorteil oder der Unterschied gegenüber der Verwendung von vuex store?
Kyle Joeckel
6

Wenn Sie versuchen, externe js-Skripte in die Komponentenvorlage vue.js einzubetten, gehen Sie wie folgt vor:

Ich wollte meiner Komponente einen externen Javascript-Einbettungscode wie folgt hinzufügen :

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

Und Vue hat mir diesen Fehler gezeigt:

Vorlagen sollten nur für die Zuordnung des Status zur Benutzeroberfläche verantwortlich sein. Vermeiden Sie das Platzieren von Tags mit Nebenwirkungen in Ihren Vorlagen, z. B. da diese nicht analysiert werden.


Die Art und Weise, wie ich es gelöst habe, war durch Hinzufügentype="application/javascript" ( Weitere Informationen zum MIME-Typ für js finden Sie in dieser Frage ):

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


Möglicherweise bemerken Sie das deferAttribut. Wenn Sie mehr erfahren möchten, schauen Sie sich dieses Video von Kyle an

roli roli
quelle
4

Sie können das benötigte Skript mit einer vielversprechenden Lösung laden:

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

    }
  }
}

Bitte beachten Sie, dass dies this.$rootein wenig hackig ist und Sie stattdessen eine vuex- oder eventHub- Lösung für die globalen Ereignisse verwenden sollten.

Sie würden das oben Genannte zu einer Komponente machen und es verwenden, wo immer es benötigt wird. Es wird das Skript nur laden, wenn es verwendet wird.

hitautodestruct
quelle
3

Dies kann einfach so gemacht werden.

  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);
    });
  }
Awais Jameel
quelle
2

Um saubere Komponenten zu halten, können Sie Mixins verwenden.

Importieren Sie auf Ihrer Komponente eine externe Mixin-Datei.

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 (ich schließe dies ein, wenn irgendwelche beim Import hängen bleiben)

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

Die beste Antwort für das Erstellen eines Tags in gemountet ist gut, hat jedoch einige Probleme: Wenn Sie Ihren Link mehrmals ändern, wird das Erstellen eines Tags immer wieder wiederholt.

Also habe ich ein Skript erstellt, um dies zu beheben, und Sie können das Tag löschen, wenn Sie möchten.

Es ist sehr einfach, kann aber Zeit sparen, um es selbst zu erstellen.

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

Und Sie können es so verwenden:

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

......
oraant
quelle
2
Sobald ein Skript geladen ist, befindet es sich bereits im Speicher. Durch das Entfernen aus dem Dom wird der Footprint nicht entfernt.
Danbars
1

Sie können den Vue-Loader verwenden und Ihre Komponenten in eigenen Dateien (Einzeldateikomponenten) codieren. Auf diese Weise können Sie Skripte und CSS auf Komponentenbasis einbinden.

Daniel D.
quelle
4
Diese Skripte sind von Paypal und Stripe. Ich kann die Datei nicht lokal herunterladen
Gijo Varghese
1
Die Verbindung ist unterbrochen
Roberto
Sie können die externen Skripte herunterladen, die Quelle anzeigen und in Ihre eigene Datei kopieren / einfügen.
Minimallinux
1
@minimallinux Im Fall von Stripe und Paypal verstößt dies gegen PCI-DSS. Also tu das nicht.
Duncan Jones
0

Die einfachste Lösung besteht darin, das Skript in die index.htmlDatei Ihres Vue-Projekts einzufügen

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>
Tanya Talwar
quelle