我们有一个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()产生的不是<component>
想要的东西。
答案 0 :(得分:1)
我猜测
parseComponent()
所产生的不是<component>
所寻找的
我想说是的,因为它似乎无法编译为任何render
函数。
如docs中所述,vue-template-compiler
用于运行时编译。而且在大多数情况下,您应该将其与vue-loader
一起使用。
我该如何进行这项工作?
您可能想使用Vue.compile
,因为它可以将模板字符串编译成render
函数;然后可以将其绑定到用于异步或动态组件的对象。
但是请注意,该功能仅在完整版本中可用,其重量比仅运行时版本的同类产品重约30%。进一步了解Runtime + Compiler vs. Runtime-only。
请牢记这一点,因为您没有在问题中提及正在使用哪个捆绑软件,所以我将假定Webpack具有Vue-CLI,以下是配置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
函数,尽管不包括<template>
标签。
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>