【问题标题】:Load Vue single-file component dynamically at runtime运行时动态加载Vue单文件组件
【发布时间】:2020-09-14 00:23:25
【问题描述】:

我们有一个 Vue 应用程序,并希望允许第三方创建插件。我们希望插件以 Vue 单文件组件的形式构建。

在运行时,最终用户会选择一个插件添加到应用程序中。该应用程序将获取纯文本 .vue 文件,即时编译它,并将其显示在应用程序中。

Vue 支持dynamic and async components,但这些需要提前编译到应用程序中。我们想做同样的事情,除了动态加载代码。

我怎样才能做到这一点?

这是我目前所得到的:

<template>
  <div>
    The component goes here:
    <component :is="pluginComponent"></component>
  </div>
</template>
<script>
import { parseComponent } from "vue-template-compiler";
export default {
  data() {
    return {
      pluginComponent: null
    };
  },
  mounted() {
    // fetch code from some external source here
    let code = "<template><div>hello</div></template>";
    let comp = parseComponent(code);
    this.pluginComponent = comp;
  }
};
</script>

(我修改了构建,因此存在 vue-template-compiler。)

上面的代码会产生这个错误:

[Vue warn]: invalid template option:[object Object]
found in
---> <Anonymous>
       <Pages/plugin/PluginId.vue> at pages/plugin/_plugin_id.vue
         <Nuxt>
           <Layouts/default.vue> at layouts/default.vue
             <Root> instrument.js:110
    instrumentConsole instrument.js:110
    VueJS 15
TypeError: "vnode is null"
    VueJS 14
instrument.js:110

我猜想无论 parseComponent() 产生什么都不是&lt;component&gt; 想要的。

【问题讨论】:

标签: javascript vue.js vue-dynamic-components


【解决方案1】:

我猜parseComponent() 产生的任何东西都不是&lt;component&gt; 正在寻找的东西

我会说是的,因为它似乎无法编译为任何 render 函数。

docs 中所述,vue-template-compiler 用于运行时编译。在大多数情况下,您应该将它与vue-loader 一起使用。

我怎样才能做到这一点?

您可能想要使用Vue.compile,因为它允许您将模板字符串编译成render 函数;然后您可以将其绑定到异步或动态组件的对象。

但请注意,这仅在完整版本中可用,比仅运行时版本的版本重约 30%。阅读更多Runtime + Compiler vs. Runtime-only

考虑到这一点,由于您没有在问题中提及您正在使用哪个捆绑程序,我将假设 Webpack 与 Vue-CLI,以下是您如何配置 vue 别名(作为导入时的参考点)。

验证你设置的 Vue“别名”

在您的控制台中(从项目的根目录),运行:

vue inspect resolve.alias.vue$

如果这导致“vue/dist/vue.runtime.esm.js”(默认情况下应该是),那么很明显我们需要更改这部分。

配置它

现在,由于内部 webpack 配置使用 webpack-chain 维护,我们将像这样配置/重置别名:

module.exports = {
  chainWebpack: config => {
    config.resolve.alias
      .set('vue$', 'vue/dist/vue.esm.js')
  }
}

查看explanation of different builds

使用它

此时,您需要做的就是将“动态”模板传递给compile 函数,但不包括&lt;template&gt; 标记。

import Vue from 'vue';

export default {
  mounted() {
    // fetch code from some external source here
    let code = '<div>hello</div>';
    let comp = Vue.compile(code);

    this.pluginComponent = comp;
  }
}
<template>
  <div>
    The component goes here:
    <component :is="pluginComponent"></component>
  </div>
</template>

【讨论】:

  • 谢谢。这有效,但仅适用于模板代码。如何使用脚本和样式部分制作完整的单文件组件?
  • 不幸的是,Vue.compile 仅用于为模板生成 render 函数。谈到&lt;script&gt; 部分,您可以尝试将内容与此编译模板合并,这需要额外的工作。但请参阅this post 的示例。至于&lt;style&gt; 部分,我在想"injecting" it on the &lt;head&gt;。 AFAIK,目前还没有一个完整的解决方案。
猜你喜欢
  • 2020-01-21
  • 2018-07-08
  • 2019-06-30
  • 2020-12-21
  • 2018-03-13
  • 2020-12-14
  • 2019-07-31
  • 2018-12-08
  • 2018-12-29
相关资源
最近更新 更多