VueJS Bileşenlerine harici JS komut dosyaları ekleme


151

Ödeme ağ geçitleri için iki harici komut dosyası kullanmalıyım. Şu anda her ikisi deindex.html dosyaya . Ancak, bu dosyaları başlangıçta yüklemek istemiyorum. Ödeme ağ geçidi yalnızca kullanıcı belirli bir bileşeni ( using router-view) açtığında gerekir .

Bunu başarabilmenin bir yolu var mı?


Bunu /public/index.htmlyapmak için kullanabilir misin ?
user3290525

Yanıtlar:


240

Bunu çözmenin basit ve etkili bir yolu, harici komut mounted()dosyanızı bileşeninizin sırasına eklemektir . Sizi Google Recaptcha betiği ile göstereceğim :

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

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


22
created()yöntemi belge alınamıyor, mounted()bunun yerine kullanın
Barlas Apaydin

15
recaptchaScript.async = trueKafasına eklemeden önce ekleyin .
Joe Eifert

6
recaptchaScript.defer = truebirisi için de uygun olabilir
Tarasovych

3
bu kesin olarak en iyi yanıttır çünkü vue tek bir dosya bileşeni çerçevesi olarak tasarlanmıştır. geçerli compnent dosyanız son derece büyük değilse, komut dosyası etiketlerinizin takılı () ve / veya beforeMount () bölümlerine işlev eklemenizi öneririm ... vuejs.org/v2/api/#beforeMount'a karar vermeden önce lütfen önceMount () işlevselliğine bakın.
Kyle Joeckel

1
@ KeeukeNagakawa teorik olarak, evet. Bu yanıtı görün stackoverflow.com/questions/1605899/…
Jeff Ryan

28

Özel js dosyaları ve jquery ile birlikte gelen bazı HTML şablonunu indirdim. Bu js benim app eklemek zorunda kaldı. ve Vue ile devam edin.

Bu eklentiyi bulduğunuzda, hem CDN üzerinden hem de statik dosyalardan harici komut dosyaları eklemenin temiz bir yoludur 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")

Bunu yapmanın gerçekten düzgün ve basit bir yolu. Bu yöntemi seviyorum
Vixson

25

webpack ve vue loader kullanarak böyle bir şey yapabilirsiniz

bileşeni oluşturmadan önce harici komut dosyasının yüklenmesini bekler, böylece bileşende globar vars vb. kullanılabilir

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

Takılı olarak kullandım
Oranit Dar

>> "Bu kodu nereye yerleştiriyorsunuz?" : Vuejs bileşeninizin bileşenler bölümünde bulunur.
ADM-IT

7

Vue için Webpack başlangıç ​​şablonlarından birini mi kullanıyorsunuz ( https://github.com/vuejs-templates/webpack )? Vue-loader ( https://github.com/vuejs/vue-loader ) ile zaten kurulmuş olarak geliyor . Başlangıç ​​şablonu kullanmıyorsanız, webpack ve vue-loader ayarlamanız gerekir.

Daha sonra importkomut dosyalarınızı ilgili (tek dosya) bileşenlere yapabilirsiniz. Bundan önce, exportkomut dosyalarınızdan importbileşenlerinize ne yapmak istediğinizi bilmeniz gerekir.

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

~ Düzenle ~
Bu sarmalayıcılardan içe aktarabilirsiniz:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout


2
Bu komut dosyaları paypal ve şeritlerden. Dosyayı yerel olarak
indiremiyorum

2
Bu sarmalayıcılar sorununuzu çözüyor mu? github.com/matfish2/vue-stripe ve github.com/khoanguyen96/vue-paypal-checkout
ba_ul

topal cevap ... vue yükleyicinin neden gerekli olduğu hakkında açıklama yap
Kyle Joeckel

6

Vue bileşeninizin başına komut dosyaları ve diğer etiketler eklemek için vue-head paketini kullanabilirsiniz.

Bu kadar basit:

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

Daha fazla örnek için bu bağlantıya göz atın .


vuex mağaza kullanarak bunun avantajı veya farkı nedir?
Kyle Joeckel

6

Harici js komut dosyalarını vue.js bileşen şablonuna katıştırmaya çalışıyorsanız, aşağıdakileri izleyin:

Böyle benim bileşen için bir dış javascript gömme kodu eklemek istedim :

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

Ve Vue bana bu hatayı gösterdi:

Şablonlar yalnızca durumu kullanıcı arayüzüyle eşlemekten sorumlu olmalıdır. Ayrıştırılmayacakları gibi şablonlarınıza yan etkileri olan etiketleri yerleştirmekten kaçının.


Ben çözme yolu ekleyerek oldutype="application/javascript" ( js için MIME türü hakkında daha fazla bilgi için bu soruya bakın ):

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


deferÖzelliği fark edebilirsiniz . Daha fazla bilgi edinmek isterseniz Kyle tarafından bu videoyu izleyin


4

İhtiyacınız olan komut dosyasını söz tabanlı bir çözümle yükleyebilirsiniz:

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

    }
  }
}

Bunun this.$rootbiraz zor olduğunu ve bunun yerine global etkinlikler için bir vuex veya eventHub çözümü kullanmanız gerektiğini lütfen unutmayın .

Yukarıdakileri bir bileşene dönüştürür ve gerektiğinde kullanırsınız, sadece kullanıldığında betiği yükler.


3

Bu basitçe böyle yapılabilir.

  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

Temiz bileşenleri tutmak için mixins kullanabilirsiniz.

Bileşeninizde harici mixin dosyasını içe aktarın.

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 (bunu dahil edersem, eğer içe aktarılırsa)

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

2

Etiketli etiket oluşturmanın en iyi yanıtı iyidir, ancak bazı sorunları vardır: Bağlantınızı birkaç kez değiştirirseniz, etiket oluşturmayı tekrar tekrar tekrarlar.

Bu yüzden bunu çözmek için bir komut dosyası oluşturdum ve isterseniz etiketi silebilirsiniz.

Çok basit, ama kendiniz oluşturmak için zaman kazanabilirsiniz.

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

Ve bunu şöyle kullanabilirsiniz:

// 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
Bir komut dosyası yüklendikten sonra zaten bellekte kalır. Dom'dan kaldırılması, kapladığı alanı kaldırmaz.
danbars

1

Vue-loader'ı kullanabilir ve bileşenlerinizi kendi dosyalarında kodlayabilirsiniz (Tek dosya bileşenleri). Bu, bileşen bazında komut dosyaları ve css eklemenize izin verir.


4
Bu komut dosyaları paypal ve şeritlerden. Dosyayı yerel olarak
indiremiyorum

1
bağlantı kopuk
Roberto

Harici komut dosyalarını indirebilir, kaynağı görüntüleyebilir, kendi dosyanıza kopyalayıp yapıştırabilirsiniz.
minimallinux

1
@minimallinux Stripe ve Paypal durumunda, bu PCI-DSS'yi ihlal edecektir. Öyleyse yapma.
Duncan Jones

0

En basit çözüm, betiği index.htmlvue-projenizin dosyasına eklemektir

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>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.