从 CDN 库动态加载 vue 组件

Posted

技术标签:

【中文标题】从 CDN 库动态加载 vue 组件【英文标题】:Load vue components from a CDN library dynamically 【发布时间】:2019-07-31 13:01:14 【问题描述】:

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

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

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

但是这种方法不起作用,因为组件尚未全局注册。 我收到以下错误:Unknown custom element: &lt;VBtn&gt;。 我也试过在window.Vuetify可用后做Vue.use(window.Veutify),问题仍然存在。

我也尝试过等待组件可用

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

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

我已经为此苦苦挣扎了一段时间。任何建议、文档、参考或不同的方法都将不胜感激,请注意我需要依赖动态加载库和动态加载其组件。

提前致谢。

【问题讨论】:

【参考方案1】:

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

加载vuetify.min.css(通常在&lt;head&gt;) 加载 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>

【讨论】:

好的,所以我试了一下,还是不行,我的项目是用webpack打包文件的,所以之前加载vue.js和vuetify.js很难。 Vue实例初始化后是否可以这样做,还是我必须重组我的项目? 是什么阻止您将 Vue 和 Vuetify 添加到包中? 需要动态加载库(veutify 只是一个示例)。我希望人们能够在指定 CDN(或者它可以是 npm 包名称)时与不同的库进行交互 您可以创建 Vue 实例 programmatically 并将它们挂载到现有实例中。

以上是关于从 CDN 库动态加载 vue 组件的主要内容,如果未能解决你的问题,请参考以下文章

Vue 动态加载组件

Vue.js - 是不是可以使用 Javascript 动态导入从另一台服务器加载组件?

vue.js 从 cdn 加载脚本,然后组件 vue(没有 webpack)

vue里面可以动态加载touchspin插件吗

vue动态加载视频问题

VUE之组件的动态注册和动态加载