简体   繁体   中英

Load vue components from a CDN library dynamically

I'm trying to load external libraries dynamically using vue. In this case those libraries have vue components that I would like to use. My current setup is the following:

  1. Load the scripts programmatically from a CDN:
// The src CDN can change.
const src = 'https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js';
const newScript = document.createElement('script');
newScript.src = src;
newScript.async = false;
newScript.type = 'text/javascript';
document.body.appendChild(newScript);
  1. Later in code I would like to use a component dynamically when it is finished loading:
<component :is="dynamicComponent" v-bind="componentProperties">
   <!-- More things inside -->
</component>

where dynamicComponent is a data property that can be changed and it is set as VBtn (have tried also v-btn ).

This approach however does not work, since components aren't yet registered globally. I get the following error: Unknown custom element: <VBtn> . I have also tried doing Vue.use(window.Veutify) after window.Vuetify is available and the problem is still present.

I have also tried waiting for the component to be available using

waitFor(() => Vue.options.components[dynamicComponent]).then(...)

however it never enters the then function. Interestingly enough when I put Vue.options.components['VBtn'] in the console I do get the component back.

I've been struggling with this for a while. Any suggestions, documentation, references or different approaches would be greatly appreciated, just note that I need to rely on dynamically loading libraries, and dynamically loading its components.

Thanks in advance.

Here are the important steps of using Vuetify, in this order:

  • load vuetify.min.css (typically in <head> )
  • load Material Icons font (if you need it)
  • load vue.js
  • load vuetify.js
  • initialize your App.

Most importantly: both vue.js and vuetify.js need to be loaded before you initialize the app.

 <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet"> <div id="app"> <v-app> <v-content> <v-btn>Hello world</v-btn> </v-content> </v-app> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script type="application/javascript"> Vue.config.devtools = false; Vue.config.productionTip = false; </script> <script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script> <script type="application/javascript"> window.onload = new Vue({ el: '#app' }); </script> 


If you really want/have to load your scripts dynamically, you can wrap them up as promises which resolve onload . Here's an example:

 const loadScript = source => new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = source; script.type = 'text/javascript'; script.onload = () => resolve(); script.onerror = event => reject(`${event.target.src} failed to load. ¯\\\\_(ツ)_/¯`); document.body.appendChild(script); }); Promise.all([ loadScript('https://cdn.jsdelivr.net/npm/vue/dist/vue.js').then(() => { Vue.config.devtools = false; Vue.config.productionTip = false; }), loadScript('https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js') ]).then( () => new Vue({ el: '#app' }), error => console.log(error), ); 
 <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet"> <div id="app"> <v-app> <v-content> <v-btn>Hello world</v-btn> </v-content> </v-app> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM