Cách thêm tập lệnh JS bên ngoài vào Thành phần VueJS


150

Tôi đã sử dụng hai tập lệnh bên ngoài cho các cổng thanh toán. Ngay bây giờ cả hai được đặt trong index.htmltập tin. Tuy nhiên, tôi không muốn tải các tệp này ngay từ đầu. Cổng thanh toán chỉ cần thiết khi người dùng mở một thành phần cụ thể ( using router-view).

Có bất kì cách nào để đạt được điều này không?


Bạn có thể sử dụng /public/index.htmlđể làm điều đó?
dùng3290525

Câu trả lời:


239

Một cách đơn giản và hiệu quả để giải quyết vấn đề này, đó là bằng cách thêm tập lệnh bên ngoài của bạn vào vue mounted()thành phần của bạn. Tôi sẽ minh họa cho bạn bằng tập lệnh 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>

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


22
created()phương pháp không thể lấy tài liệu, sử dụng mounted()thay thế
Barlas Apaydin

15
Thêm recaptchaScript.async = truetrước khi gắn nó vào đầu.
Joe Eifert

6
recaptchaScript.defer = truecũng có thể phù hợp với ai đó
Tarasovych

3
điều này chắc chắn là câu trả lời tốt nhất vì vue được dự định là một khung thành phần tệp duy nhất. trừ khi tệp công ty hiện tại của bạn cực kỳ lớn, tôi sẽ khuyên bạn nên thêm phần funcionto các phần được gắn () và / hoặc beforeMount () của thẻ script của bạn ... vui lòng xem chức năng beforeMount () trước khi quyết định vuejs.org/v2/api/#b BeforeMount
Kyle Joeckel

1
@KeisukeNagakawa về mặt lý thuyết, vâng. Xem câu trả lời này stackoverflow.com/questions/1605899/ Mạnh
Jeff Ryan

28

Tôi đã tải xuống một số mẫu HTML đi kèm với các tệp js và jquery tùy chỉnh. Tôi đã phải đính kèm những js vào ứng dụng của tôi. và tiếp tục với Vue.

Đã tìm thấy plugin này, đây là một cách sạch để thêm các tập lệnh bên ngoài thông qua CDN và từ các tệp tĩnh 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")

Đây là một cách thực sự gọn gàng và đơn giản để làm điều đó. Tôi thích phương pháp này
Vixson

25

sử dụng webpack và vue loader bạn có thể làm một cái gì đó như thế này

nó chờ tập lệnh bên ngoài tải trước khi tạo thành phần, vì vậy vars globar v.v. có sẵn trong thành phần

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

Tôi đã sử dụng nó trong gắn kết
Oranit Dar

>> "Bạn đặt mã này ở đâu?" : Nó nằm trong phần thành phần trong thành phần vuejs của bạn.
ADM-IT

7

Bạn có đang sử dụng một trong các mẫu khởi động Webpack cho vue ( https://github.com/vuejs-temsheet/webpack ) không? Nó đã được thiết lập với vue-loader ( https://github.com/vuejs/vue-loader ). Nếu bạn không sử dụng mẫu khởi động, bạn phải thiết lập gói webpack và trình tải vue.

Sau đó, importbạn có thể tập lệnh của mình đến các thành phần (tệp đơn) có liên quan. Trước đó, bạn phải exporttừ các kịch bản của bạn những gì bạn muốn importđến các thành phần của bạn.

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

~ Chỉnh sửa ~
Bạn có thể nhập từ các trình bao bọc này:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout


2
Các kịch bản này là từ paypal và sọc. Tôi không thể tải xuống tệp đặt cục bộ
Gijo Varghese

2
Những bao bì này giải quyết vấn đề của bạn? github.com/matfish2/vue-stripegithub.com/khoanguyen96/vue-paypal-checkout
ba_ul

câu trả lời khập khiễng ... đưa ra lời giải thích tại sao cần phải tải vue
Kyle Joeckel

6

Bạn có thể sử dụng gói vue-head để thêm tập lệnh và các thẻ khác vào phần đầu của thành phần vue.

Nó đơn giản như:

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

Kiểm tra liên kết này để biết thêm ví dụ.


lợi thế hay sự khác biệt của việc này khi sử dụng cửa hàng vuex là gì?
Kyle Joeckel

6

Nếu bạn đang cố gắng nhúng các tập lệnh js bên ngoài vào mẫu thành phần vue.js, hãy làm theo bên dưới:

Tôi muốn thêm một mã nhúng javascript bên ngoài vào thành phần của mình như thế này:

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

Và Vue chỉ cho tôi lỗi này:

Các mẫu chỉ có trách nhiệm ánh xạ trạng thái tới UI. Tránh đặt các thẻ có tác dụng phụ trong các mẫu của bạn, chẳng hạn như, vì chúng sẽ không được phân tích cú pháp.


Cách tôi giải quyết là bằng cách thêmtype="application/javascript" ( Xem câu hỏi này để tìm hiểu thêm về loại MIME cho js ):

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


Bạn có thể nhận thấy deferthuộc tính. Nếu bạn muốn tìm hiểu thêm hãy xem video này của Kyle


4

Bạn có thể tải tập lệnh bạn cần bằng một giải pháp dựa trên lời hứa:

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

    }
  }
}

Hãy lưu ý rằng this.$rootlà một hacky chút và bạn nên sử dụng một vuex hoặc eventHub giải pháp cho các sự kiện toàn cầu để thay thế.

Bạn sẽ biến phần trên thành một thành phần và sử dụng nó bất cứ khi nào cần, nó sẽ chỉ tải tập lệnh khi được sử dụng.


3

Điều này có thể được thực hiện đơn giản như thế này.

  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

Để giữ sạch các thành phần, bạn có thể sử dụng mixins.

Trên thành phần của bạn nhập tập tin mixin bên ngoài.

Hồ sơ.vue

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

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

bên ngoàiJs.js

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

babelrc (Tôi bao gồm cái này, nếu có bị kẹt khi nhập)

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

2

Câu trả lời hàng đầu của thẻ tạo trong gắn kết là tốt, nhưng nó có một số vấn đề: Nếu bạn thay đổi liên kết của mình nhiều lần, nó sẽ lặp đi lặp lại tạo thẻ nhiều lần.

Vì vậy, tôi đã tạo một tập lệnh để giải quyết vấn đề này và bạn có thể xóa thẻ nếu muốn.

Điều đó rất đơn giản, nhưng có thể tiết kiệm thời gian của bạn để tự tạo ra nó.

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

Và bạn có thể sử dụng nó như thế này:

// 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
Khi tập lệnh được tải, nó đã có trong bộ nhớ. Loại bỏ nó khỏi dom không loại bỏ dấu chân của nó.
danbars

1

Bạn có thể sử dụng trình tải vue và mã các thành phần của mình trong các tệp riêng của chúng (Các thành phần tệp đơn). Điều này sẽ cho phép bạn bao gồm các tập lệnh và css trên cơ sở thành phần.


4
Các kịch bản này là từ paypal và sọc. Tôi không thể tải xuống tệp đặt cục bộ
Gijo Varghese

1
liên kết bị hỏng
Roberto

Bạn có thể tải xuống các tập lệnh bên ngoài, xem nguồn, sao chép / dán vào tập tin của riêng bạn.
minimallinux

1
@minimallinux Trong trường hợp của Stripe và Paypal, điều đó sẽ vi phạm PCI-DSS. Vì vậy, đừng làm điều đó.
Duncan Jones

0

Giải pháp đơn giản nhất là thêm tập lệnh trong index.htmltệp của dự án vue của bạn

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>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.