[英]Load Vue single-file component dynamically at runtime
We've got a Vue app and would like to allow third parties to create plugins.我们有一个 Vue 应用程序,并希望允许第三方创建插件。 We'd like the plugins to be built in the form of a Vue single-file component.
我们希望插件以 Vue 单文件组件的形式构建。
At runtime, the end user would select a plugin to add to the app.在运行时,最终用户将 select 一个插件添加到应用程序中。 The app would fetch the plain-text.vue file, compile it on the fly, and display it in the app.
该应用程序将获取 plain-text.vue 文件,即时编译它,并将其显示在应用程序中。
Vue supports dynamic and async components , but these to be compiled into the app ahead of time. Vue 支持动态和异步组件,但这些要提前编译到应用程序中。 We'd like to do the same thing, except load the code on the fly.
我们想做同样的事情,除了动态加载代码。
How can I make this work?我怎样才能使这项工作?
Here's what I've got so far:这是我到目前为止所得到的:
<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>
(I modified the build so the vue-template-compiler is present.) (我修改了构建,因此存在 vue-template-compiler。)
The code above generates this error:上面的代码生成此错误:
[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
I'm guessing that whatever parseComponent() produces isn't what <component>
is looking for.我猜测无论 parseComponent() 产生什么,都不是
<component>
正在寻找的。
I'm guessing that whatever
parseComponent()
produces isn't what<component>
is looking for我猜无论
parseComponent()
产生什么都不是<component>
正在寻找的
I'd say yes, as it doesn't seem to compile to any render
functions.我会说是的,因为它似乎没有编译成任何
render
函数。
As stated in the docs , vue-template-compiler
is for runtime-compilation.如文档中所述,
vue-template-compiler
用于运行时编译。 And in most cases you should be using it with vue-loader
.在大多数情况下,你应该将它与
vue-loader
一起使用。
How can I make this work?
我怎样才能使这项工作?
You might want to use Vue.compile
as it allows you to compile template string into a render
function;你可能想使用
Vue.compile
,因为它允许你将模板字符串编译成render
function; which you can then bind to an object for an async or dynamic component.然后您可以将其绑定到异步或动态组件的 object。
Do note, however, that this is only available in the full build , which is roughly 30% heavier-weight than the runtime-only build counterparts.但是请注意,这仅在完整构建中可用,它比仅运行时构建对应物重约 30%。 Read more on Runtime + Compiler vs. Runtime-only .
阅读有关运行时 + 编译器与仅运行时的更多信息。
With that in mind, since you didn't mention in the question, which bundler you are using, I'm going to assume Webpack with Vue-CLI, and here's how you would configure the vue
alias (as a reference point when importing).考虑到这一点,因为你没有在问题中提到你正在使用哪个捆绑器,我将假设 Webpack 与 Vue-CLI,这里是你如何配置
vue
别名(作为导入时的参考点) .
In your console (from the root of the project), run:在您的控制台中(从项目的根目录),运行:
vue inspect resolve.alias.vue$
If that results in something along "vue/dist/vue.runtime.esm.js" (it should be, by default), then it's clear that we need to change this part.如果这导致“vue/dist/vue.runtime.esm.js”(默认情况下应该是),那么很明显我们需要更改这部分。
Now, since the internal webpack config is maintained using webpack-chain
, we would configure/reset the alias like so:现在,由于内部 webpack 配置是使用
webpack-chain
维护的,我们将像这样配置/重置别名:
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set('vue$', 'vue/dist/vue.esm.js')
}
}
Check out the explanation of different builds .查看不同构建的解释。
And at this point, all you'd need to do is pass the "dynamic" template to the compile
function, excluding the <template>
tag though.此时,您需要做的就是将“动态”模板传递给
compile
function,但不包括<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.