Bagaimana cara menambahkan skrip JS eksternal ke Komponen VueJS


150

Saya sudah menggunakan dua skrip eksternal untuk gateway pembayaran. Saat ini keduanya dimasukkan ke dalam index.htmlfile. Namun, saya tidak ingin memuat file-file ini di awal. Gateway pembayaran hanya diperlukan saat pengguna membuka komponen tertentu ( using router-view).

Apakah ada cara untuk mencapai hal ini?


Bisakah Anda menggunakannya /public/index.htmluntuk melakukannya?
user3290525

Jawaban:


239

Cara sederhana dan efektif untuk menyelesaikan ini, itu dengan menambahkan skrip eksternal Anda ke dalam vue mounted()komponen Anda. Saya akan mengilustrasikan Anda dengan skrip 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>

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


22
created()metode tidak bisa mendapatkan dokumen, gunakan mounted()sebagai gantinya
Barlas Apaydin

15
Tambahkan recaptchaScript.async = truesebelum menambahkannya ke kepala.
Joe Eifert

6
recaptchaScript.defer = truemungkin juga cocok untuk seseorang
Tarasovych

3
ini pasti jawaban terbaik karena vue dimaksudkan untuk menjadi kerangka kerja komponen file tunggal. kecuali jika file compnent Anda saat ini sangat besar saya sarankan menambahkan fungsi ke bagian mount () dan / atau beforeMount () tag Anda ... silakan lihat fungsionalitas beforeMount () sebelum memutuskan vuejs.org/v2/api/#beforeMount
Kyle Joeckel

1
@KeisukeNagakawa secara teoritis, ya. Lihat jawaban ini stackoverflow.com/questions/1605899/...
Jeff Ryan

28

Saya telah mengunduh beberapa templat HTML yang dilengkapi dengan file dan jquery js khusus. Saya harus melampirkan js itu ke aplikasi saya. dan lanjutkan dengan Vue.

Ditemukan plugin ini, ini adalah cara bersih untuk menambahkan skrip eksternal baik melalui CDN dan dari file statis 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")

Ini cara yang sangat rapi dan sederhana untuk melakukannya. Saya suka metode ini
Vixson

25

menggunakan webpack dan vue loader Anda dapat melakukan sesuatu seperti ini

menunggu skrip eksternal untuk memuat sebelum membuat komponen, sehingga varsar dll tersedia dalam komponen

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

Saya menggunakannya di mount
Oranit Dar

>> "Di mana Anda menempatkan kode ini?" : Ada di bagian komponen di komponen vuejs Anda.
ADM-IT

7

Apakah Anda menggunakan salah satu templat starter Webpack untuk vue ( https://github.com/vuejs-templates/webpack )? Sudah diatur dengan vue-loader ( https://github.com/vuejs/vue-loader ). Jika Anda tidak menggunakan template pemula, Anda harus mengatur webpack dan vue-loader.

Anda kemudian dapat importskrip Anda ke komponen (file tunggal) yang relevan. Sebelum itu, Anda harus exportdari skrip apa yang Anda inginkan ke importkomponen Anda.

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

~ Sunting ~
Anda dapat mengimpor dari pembungkus ini:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout


2
Script ini dari paypal dan stripe. Saya tidak dapat mengunduh file yang diletakkan secara lokal
Gijo Varghese

2
Apakah pembungkus ini menyelesaikan masalah Anda? github.com/matfish2/vue-stripe dan github.com/khoanguyen96/vue-paypal-checkout
ba_ul

jawaban lumpuh ... berikan penjelasan mengapa vue loader diperlukan
Kyle Joeckel

6

Anda dapat menggunakan paket vue-head untuk menambahkan skrip, dan tag lain ke kepala komponen vue Anda.

Sesederhana:

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

Lihatlah tautan ini untuk lebih banyak contoh.


apa keuntungan atau perbedaan dari ini menggunakan vuex store?
Kyle Joeckel

6

Jika Anda mencoba menyematkan skrip js eksternal ke templat komponen vue.js, ikuti di bawah ini:

Saya ingin menambahkan kode sematan javascript eksternal ke komponen saya seperti ini:

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

Dan Vue menunjukkan kepada saya kesalahan ini:

Template seharusnya hanya bertanggung jawab untuk memetakan keadaan ke UI. Hindari menempatkan tag dengan efek samping di templat Anda, seperti, karena tidak akan diuraikan.


Cara saya menyelesaikannya adalah dengan menambahkantype="application/javascript" ( Lihat pertanyaan ini untuk mempelajari lebih lanjut tentang tipe MIME untuk js ):

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


Anda mungkin memperhatikan deferatributnya. Jika Anda ingin mempelajari lebih lanjut tonton video ini oleh Kyle


4

Anda dapat memuat skrip yang Anda butuhkan dengan solusi berbasis janji:

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

    }
  }
}

Harap perhatikan bahwa this.$rootini sedikit hacky dan Anda harus menggunakan solusi vuex atau eventHub untuk acara global.

Anda akan membuat hal di atas menjadi komponen dan menggunakannya di mana pun dibutuhkan, itu hanya akan memuat skrip saat digunakan.


3

Ini bisa dilakukan seperti ini.

  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

Untuk menjaga kebersihan komponen, Anda dapat menggunakan mixin.

Pada komponen Anda mengimpor file mixin eksternal.

Profil

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 (saya sertakan ini, jika ada yang macet saat impor)

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

2

Jawaban atas tag buat di mount baik, tetapi memiliki beberapa masalah: Jika Anda mengubah tautan beberapa kali, itu akan mengulangi membuat tag berulang-ulang.

Jadi saya membuat skrip untuk menyelesaikan ini, dan Anda dapat menghapus tag jika mau.

Ini sangat sederhana, tetapi dapat menghemat waktu Anda untuk membuatnya sendiri.

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

Dan Anda dapat menggunakannya seperti ini:

// 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
Setelah skrip dimuat, sudah ada dalam memori. Menghapusnya dari dom tidak menghapus jejaknya.
danbars

1

Anda dapat menggunakan vue-loader dan kode komponen Anda di file mereka sendiri (Komponen file tunggal). Ini akan memungkinkan Anda untuk memasukkan skrip dan css berdasarkan komponen.


4
Script ini dari paypal dan stripe. Saya tidak dapat mengunduh file yang diletakkan secara lokal
Gijo Varghese

1
tautannya rusak
Roberto

Anda dapat mengunduh skrip eksternal, melihat sumber, menyalin / menempel ke file Anda sendiri.
minimallinux

1
@minimallinux Dalam kasus Stripe dan Paypal, itu akan melanggar PCI-DSS. Jadi jangan lakukan itu.
Duncan Jones

0

Solusi paling sederhana adalah dengan menambahkan skrip dalam index.htmlfile vue-project Anda

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>
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.