We've got a Vue app and would like to allow third parties to create plugins. We'd like the plugins to be built in the form of a Vue single-file ponent.
At runtime, the end user would select a plugin to add to the app. The app would fetch the plain-text .vue file, pile it on the fly, and display it in the app.
Vue supports dynamic and async ponents, but these to be piled into the app ahead of time. 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 ponent goes here:
<ponent :is="pluginComponent"></ponent>
</div>
</template>
<script>
import { parseComponent } from "vue-template-piler";
export default {
data() {
return {
pluginComponent: null
};
},
mounted() {
// fetch code from some external source here
let code = "<template><div>hello</div></template>";
let p = parseComponent(code);
this.pluginComponent = p;
}
};
</script>
(I modified the build so the vue-template-piler is present.)
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 <ponent>
is looking for.
We've got a Vue app and would like to allow third parties to create plugins. We'd like the plugins to be built in the form of a Vue single-file ponent.
At runtime, the end user would select a plugin to add to the app. The app would fetch the plain-text .vue file, pile it on the fly, and display it in the app.
Vue supports dynamic and async ponents, but these to be piled into the app ahead of time. 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 ponent goes here:
<ponent :is="pluginComponent"></ponent>
</div>
</template>
<script>
import { parseComponent } from "vue-template-piler";
export default {
data() {
return {
pluginComponent: null
};
},
mounted() {
// fetch code from some external source here
let code = "<template><div>hello</div></template>";
let p = parseComponent(code);
this.pluginComponent = p;
}
};
</script>
(I modified the build so the vue-template-piler is present.)
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 <ponent>
is looking for.
- 3 Thihs should do what you want ... markus.oberlehner/blog/… – mark-hahn Commented Oct 11, 2020 at 4:01
- @mark-hahn This is the answer. Thank you. – ccleve Commented Oct 13, 2020 at 1:02
- 1 Have a look at this answer: stackoverflow./a/42020118/138579 (disclaimer: author here) – Franck Freiburger Commented Dec 4, 2020 at 12:00
1 Answer
Reset to default 4I'm guessing that whatever
parseComponent()
produces isn't what<ponent>
is looking for
I'd say yes, as it doesn't seem to pile to any render
functions.
As stated in the docs, vue-template-piler
is for runtime-pilation. And in most cases you should be using it with vue-loader
.
How can I make this work?
You might want to use Vue.pile
as it allows you to pile template string into a render
function; which you can then bind to an object for an async or dynamic ponent.
Do note, however, that this is only available in the full build, which is roughly 30% heavier-weight than the runtime-only build counterparts. 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).
Verifying your set Vue "alias"
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.
Configuring it
Now, since the internal webpack config is maintained using webpack-chain
, we would configure/reset the alias like so:
module.exports = {
chainWebpack: config => {
config.resolve.alias
.set('vue$', 'vue/dist/vue.esm.js')
}
}
Check out the explanation of different builds.
Using it
And at this point, all you'd need to do is pass the "dynamic" template to the pile
function, excluding the <template>
tag though.
import Vue from 'vue';
export default {
mounted() {
// fetch code from some external source here
let code = '<div>hello</div>';
let p = Vue.pile(code);
this.pluginComponent = p;
}
}
<template>
<div>
The ponent goes here:
<ponent :is="pluginComponent"></ponent>
</div>
</template>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745281375a4620295.html
评论列表(0条)