Reputation: 1491
Is there any way to provide html for Vue instance? With default, named and scoped slots? Just like with components, but instead to Vue instance.
I've create a simple demo here https://codesandbox.io/s/frosty-pine-v9dkn
main.js
const compTemplate =
'<p>main content</p><template v-slot:header="coolName">{{ coolName }}</template><template v-slot:footer>footer contnet</template>';
// How to send compTemplate to App?
new Vue({
render: (h) => h(App)
}).$mount("#app");
App.vue
<template>
<div id="app">
<header><slot name="header" :coolName="coolName"></slot></header>
<slot></slot>
<footer><slot name="footer"></slot></footer>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
data() {
return {
coolName: "Some Cool Name",
};
},
components: {
HelloWorld,
},
};
</script>
Upvotes: 0
Views: 1040
Reputation: 8329
If you put HTML in a slot, then it's going to appear as plain text. You might have some close options though, depending on your use-case:
Vue.component('SimpleComponent', {
template: `
<div
style="font-weight: 700"
>
I'm formatted with HTML.
</div>
`
})
Vue.component('SlotContainer', {
template: `
<div>
<slot name="header"></slot><br />
<slot></slot><br />
<slot name="footer"></slot>
</div>
`
})
new Vue({
el: "#app",
template: `
<slot-container>
<template slot="header">
header
</template>
<template slot="default">
<simple-component></simple-component>
</template>
<template slot="footer">
footer
</template>
</slot-container>
`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
Vue.component('PropsContainer', {
props: ['header', 'body', 'footer'],
template: `
<div>
<header v-html="header"></header><br />
<div v-html="body"></div><br />
<footer v-html="footer"></footer>
</div>
`
})
new Vue({
el: "#app",
data() {
return {
bodyHTML: "<strong>I'm formatted with HTML</strong>"
}
},
template: `
<props-container
:header="'header'"
:body="bodyHTML"
:footer="'footer'"
>
</props-container>
`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
This one would use v-html
, that requires extra attention because of security issues (especially, if you want to put out user input).
What you provided as an example is NOT a simple HTML string, it's a Vue template:
const compTemplate = '<p>main content</p><template v-slot:header="coolName">{{ coolName }}</template><template v-slot:footer>footer contnet</template>'
If you want that, then you might need a more advanced approach, you need to compile these templates runtime.
const compTemplate =
`
<div>
<p>main content</p>
<template v-slot:header="coolName">{{ coolName }} header content</template><br />
<template v-slot:footer>footer content</template>
</div>
`
Vue.component('RenderComponent', {
props: ['html'],
render(h) {
return h({
template: `<div>${ this.html }</div>`
})
}
})
new Vue({
el: "#app",
data() {
return {
compTemplate
}
},
template: `
<render-component
:html="compTemplate"
>
</render-component>
`
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>
Upvotes: 2