I am currently attempting to render HTML at runtime using Vue3 (and no, v-html
isn't sufficient for my needs because I have a custom component that needs to be rendered within the HTML). How do I go about doing this?
-
I couldn't reproduce the problem, it works fine for me as is. Maybe you can show your templates– DanCommented Nov 18, 2020 at 9:43
-
@Dan I made a really simplistic project to try and get a repro that I could share...and it worked. Looks like there's something else going on, so now I just have to find it. I'll update the question once I locate the issue.– One CrayonCommented Nov 18, 2020 at 17:32
1 Answer
Turns out that what was preventing this from working for me was a circular import in my component, so I'll answer it on my own! In Vue3 it's much easier to render arbitrary HTML including components via a component. Here's a bit of stub code that shows an example of how to do this:
// IMPORTANT: you must import `compile` from this file! Standard Vue builds won't work
import { compile } from 'vue/dist/vue.esm-bundler.js'
// Include custom components that are embedded in your HTML here
import CustomComponent from './CustomComponent.vue'
export default {
name: 'CustomContent',
// The `content` prop should contain your HTML; you could alternately make it Markdown
// or something and parse that in the `setup` method
props: ['content'],
components: {
CustomComponent,
},
setup (props) {
// Setup accepts a reactive `props` object and can return a render function, so this
// functionally allows us to compile arbitrary HTML into Vue components
return compile(props.content)
},
}
That's it! The main caveats are all noted in the comments, and you can include as many custom components as you wish. Just watch out for circular imports in your custom components. ;-)
(Incidentally, you can work around a circular import by defining one of the components globally instead, which is how I ended up solving my actual issue.)
-
This is great! Do you know how I could update the content on prop change?– JammerCommented Sep 23, 2021 at 10:29
-
Off the top of my head, no. That might be worth a question of its own. Commented Sep 30, 2021 at 23:41