javascript - Load Vue single-file component dynamically at runtime - Stack Overflow

We've got a Vue app and would like to allow third parties to create plugins. We'd like the pl

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.

Share Improve this question edited Jul 14, 2022 at 2:24 tony19 139k23 gold badges278 silver badges348 bronze badges asked May 27, 2020 at 3:35 ccleveccleve 15.8k29 gold badges101 silver badges172 bronze badges 3
  • 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
Add a ment  | 

1 Answer 1

Reset to default 4

I'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条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信