从CDN库动态加载Vue组件

时间:2019-03-09 19:25:28

标签: javascript vue.js dynamic components load

我正在尝试使用vue动态加载外部库。在这种情况下,那些库具有我要使用的vue组件。我当前的设置如下:

  1. 以编程方式从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. 稍后在代码中,我想在组件加载完成后动态使用它:
<component :is="dynamicComponent" v-bind="componentProperties">
   <!-- More things inside -->
</component>

其中dynamicComponent是可以更改的数据属性,它设置为VBtn(也尝试过v-btn)。

但是,此方法行不通,因为尚未在全球范围内注册组件。 我收到以下错误:Unknown custom element: <VBtn>。 在Vue.use(window.Veutify)可用并且问题仍然存在之后,我也尝试过进行window.Vuetify

我也尝试过等待组件可用,

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

但是它永远不会进入then函数。有趣的是,当我将Vue.options.components['VBtn']放入控制台时,我确实将组件拿回了。

我一直为此苦苦挣扎。任何建议,文档,参考或其他方法都将不胜感激,只需注意我需要依靠动态加载库以及动态加载其组件。

谢谢。

1 个答案:

答案 0 :(得分:0)

以下是按顺序使用Vuetify的重要步骤:

  • 加载vuetify.min.css(通常在<head>中)
  • 加载Material Icons字体(如果需要)
  • 加载vue.js
  • 加载vuetify.js
  • 初始化您的应用。

最重要的是:在初始化应用程序之前,都需要加载vue.jsvuetify.js

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


如果您确实希望/必须动态加载脚本,则可以将它们包装为可以解决onload的Promise。这是一个示例:

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>