如何将外部JS脚本添加到VueJS组件

Gij*_*ese 94 javascript vue.js vue-router vue-component vuejs2

我将使用两个外部脚本作为支付网关.现在两者都放在'index.html'文件中.但是,我不想在开头加载这些文件.仅当用户打开特定组件(使用路由器视图)时才需要支付网关.反正有没有实现这个目标?

mej*_*l57 160

解决此问题的一种简单有效的方法是将外部脚本添加到mounted()组件的vue 中.我将使用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>
Run Code Online (Sandbox Code Playgroud)

资料来源:https://medium.com/@lassiuosukainen/how-to-include-a-script-tag-on-a-vue-component-fe10940af9e8

  • `created()`方法无法获取文件,请改用`mounted()` (19认同)
  • 在将它附加到头部之前添加`recaptchaScript.async = true`. (10认同)
  • 之后使用脚本定义的变量,即使将 defer 设置为 false,也不起作用。示例:加载 https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js mapboxgl.accessToken = 123。为此必须使用 vue-plugin-load-script .then()上班。 (5认同)
  • `recaptchaScript.defer = true`也许适合某人 (3认同)
  • @marius您应该向该脚本添加一个 onLoad 事件侦听器和事件处理程序。意思是当脚本 onLoad 事件触发时运行的函数。 (3认同)
  • 无疑,这是最好的答案,因为vue旨在成为单个文件组件框架。除非您当前的组件文件非常大,否则我建议将功能添加到脚本标签的mount()和/或beforeMount()部分...在决定https://vuejs.org/v2/之前,请先查看beforeMount()功能。 api /#beforeMount (2认同)

rol*_*oli 23

如果您尝试将外部 js 脚本嵌入到 vue.js 组件模板中,请按照以下步骤操作:

我想向我的组件添加一个外部 javascript 嵌入代码,如下所示:

<template>
  <div>
    This is my component
    <script src="https://badge.dimensions.ai/badge.js"></script>
  </div>
<template>
Run Code Online (Sandbox Code Playgroud)

Vue 向我展示了这个错误:

模板应该只负责将状态映射到 UI。避免在模板中放置带有副作用的标签,例如 ,因为它们不会被解析。


我解决它的方法是添加type="application/javascript"请参阅此问题以了解有关 js 的 MIME 类型的更多信息):

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


您可能会注意到该defer属性。如果您想了解更多信息,请观看Kyle 的此视频

  • VueCompilerError:客户端组件模板中会忽略具有副作用的标签(&lt;script&gt; 和 &lt;style&gt;)。 (2认同)

mon*_*oid 19

使用webpack和vue loader你可以做这样的事情

它在创建组件之前等待外部脚本加载,因此组件中可以使用globar vars等

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)
  })
 }
},
Run Code Online (Sandbox Code Playgroud)


PJ3*_*PJ3 18

我已经下载了一些自定义js文件和jquery附带的HTML模板.我不得不将这些js附加到我的应用程序中.并继续Vue.

找到这个插件,这是一个通过CDN和静态文件添加外部脚本的简洁方法 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")
Run Code Online (Sandbox Code Playgroud)

  • 这个 Vue.loadScript() 位于哪个文件中?是App.vue 文件吗? (9认同)

Pau*_*aul 12

在 Vue 3 中,我使用mejiamanuel57答案进行额外检查,以确保脚本标记尚未加载。

    mounted() {
        const scripts = [
            "js/script1.js",
            "js/script2.js"
        ];
        scripts.forEach(script => {
            let tag = document.head.querySelector(`[src="${ script }"`);
            if (!tag) {
                tag = document.createElement("script");
                tag.setAttribute("src", script);
                tag.setAttribute("type", 'text/javascript');
                document.head.appendChild(tag); 
            }
        });
    // ...
Run Code Online (Sandbox Code Playgroud)


小智 11

这可以像这样简单地完成。

  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);
    });
  }
Run Code Online (Sandbox Code Playgroud)


Lui*_*íaz 10

我发现的一种快速而简单的方法是这样的:

<template>
    <div>Some HTML</div>
    <component
        src="https://unpkg.com/flowbite@1.5.3/dist/flowbite.js"
        :is="'script'"
    ></component>
</template>
Run Code Online (Sandbox Code Playgroud)


hit*_*uct 9

您可以使用基于承诺的解决方案加载您需要的脚本:

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

    }
  }
}
Run Code Online (Sandbox Code Playgroud)

请注意,this.$root这有点麻烦,您应该为全局事件使用vuexeventHub解决方案。

您可以将上述内容制作成一个组件并在需要的地方使用它,它只会在使用时加载脚本。

注意:这是一个基于 Vue 2.x 的解决方案。Vue 3 已停止支持$on.


pam*_*kar 7

您可以使用vue-head包将脚本和其他标签添加到 vue 组件的头部。

它很简单:

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 },
      // ...
    ]
  }
})
Run Code Online (Sandbox Code Playgroud)

查看此链接以获取更多示例。


ora*_*ant 6

在mounted中创建标签的最佳答案是好的,但它有一些问题:如果多次更改链接,它会一遍又一遍地重复创建标签。

所以我创建了一个脚本来解决这个问题,如果你愿意,你可以删除标签。

这很简单,但可以节省您自己创建的时间。

// 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,
}
Run Code Online (Sandbox Code Playgroud)

你可以像这样使用它:

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

......
Run Code Online (Sandbox Code Playgroud)

  • 一旦脚本被加载,它就已经在内存中了。从 dom 中删除它并不会删除它的足迹。 (2认同)

小智 6

最简单的解决方案是将脚本添加到index.htmlvue-project 的文件中

索引.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>
Run Code Online (Sandbox Code Playgroud)


ba_*_*_ul 5

您是否正在使用其中一个Webpack启动器模板(https://github.com/vuejs-templates/webpack)?它已经设置了vue-loader(https://github.com/vuejs/vue-loader).如果您没有使用入门模板,则必须设置webpack和vue-loader.

然后,您可以import将脚本发送到相关(单个文件)组件.在此之前,您必须export从脚本中将所需内容添加import到组件中.

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

〜编辑〜
你可以从这些包装中导入:
- https://github.com/matfish2/vue-stripe
- https://github.com/khoanguyen96/vue-paypal-checkout

  • 这些脚本来自贝宝和条纹。我无法在本地下载放置文件 (2认同)
  • 这些包装纸能解决您的问题吗?https://github.com/matfish2/vue-stripe和https://github.com/khoanguyen96/vue-paypal-checkout (2认同)

Ale*_*lex 5

mejiamanuel57 的答案很棒,但我想添加一些适用于我的案例的技巧(我花了几个小时在上面)。首先,我需要使用“窗口”范围。此外,如果您需要访问“onload”函数内的任何 Vue 元素,则需要为“this”实例添加一个新变量。

<script>
import { mapActions } from "vuex";
export default {
  name: "Payment",
  methods: {
    ...mapActions(["aVueAction"])
  },
  created() {
    let paywayScript = document.createElement("script");
    let self = this;
    paywayScript.onload = () => {
      // call to Vuex action.
      self.aVueAction();
      // call to script function
      window.payway.aScriptFunction();
    };
    // paywayScript.async = true;
    paywayScript.setAttribute(
      "src",
      "https://api.payway.com.au/rest/v1/payway.js"
    );
    document.body.appendChild(paywayScript);
  }
};
</script>
Run Code Online (Sandbox Code Playgroud)

我在 Vue 2.6 上使用过这个。这里有一个关于“让自我=这个;”技巧的解释。在 Javascript 中工作:

'var that = this;' 是什么意思 在 JavaScript 中是什么意思?