EN VI

Vue.js - How to compile a Vue template with other components?

2024-03-10 19:30:07
Vue.js - How to compile a Vue template with other components?

It's often needed to patch and compile a HTML (in my case a SVG) returned from a backend.

I used only the simplest version as

import {compile} from 'vue'; 
const component = compile(text);

But now I patch the source with DOM and inject other components inside it. For that I need to use app.component() to register all the injected components.

That's bad obviously for several known reasons.

Could we inject locally imported components? Like:

import Tooltip from 'Tooltip.vue';
import {compile} from 'vue'; 
const component = compile(text, {components:[Tooltip]});

Definitely compile has an extensive set of options:

https://github.com/vuejs/core/blob/fef2acb2049fce3407dff17fe8af1836b97dfd73/packages/compiler-core/src/options.ts

But I can't find anything about injecting components.

There are several ideas but need prolonged tries and errors like:

  1. Compile as SFC and inject dependencies somehow
  2. Provide components in ctx somehow on a render
  3. Somehow do it with defineComponent

But I can't figure a proper direction to follow, any help would be appreciated.

The only working way I've found so far is with <component> but I'd like to use component names directly as tags (of cause I can patch the source to change custom components to <component> but anyway):

<script setup>
import { compile, h } from 'vue'

const comp = compile('<component :is="test"></component>');
const test = () => h('div', 'TEST');
</script>

<template>
  <comp :test/>
</template>

Solution:

compile compiles a template to render function that resolves components by their names, i.e. <SomeComp> becomes h(resolveComponent('SomeComp'), this requires SomeComp component to be registered in the context where render function is used, this doesn't require special treatment from compile.

In this case it could be:

const DummyComponent = {
  name: 'DummyComponent',
  render: compile(`<div><SomeComp/></div>`),
  components: { SomeComp }
};

And rendered as any dynamic component, e.g. in a template:

<component :is="DummyComponent"></component>
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login