I think your issue comes from a misunderstanding of how <slot>
inherently works in VueJS. Slots are used to interweave content from a consuming parent component into a child component. See it as a HTML equivalent of v-bind:prop
. When you use v-bind:prop
on a component, you are effectively passing data into a child component. This is the same as slots.
Without any concrete example or code from your end, this answer is at best just guess-work. I assume that your parent component is a VueJS app itself, and the child component is the one that holds the <slot>
element.
<!-- Parent template -->
<div id="app">
<custom-component>
<!-- content here -->
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
In this case, the app has a default ground state where it passes static HTML to the child component:
<!-- Parent template -->
<div id="app">
<custom-component>
<!-- Markup to be interweaved into custom component -->
<p>Lorem ipsum dolor sit amet.</p>
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
Then, when an event is fired, you want to replace that ground-state markup with new incoming markup. This can be done by storing the incoming HTML in the data
attribute, and simply using v-html
to conditionally render it. Let's say we want to store the incoming markup in app's vm.$data.customHTML
:
data: {
customHTML: null
}
Then your template will look like this:
<!-- Parent template -->
<div id="app">
<custom-component>
<div v-if="customHTML" v-html="customHTML"></div>
<div v-else>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</custom-component>
</div>
<!-- Custom component template -->
<template>
<slot></slot>
</template>
Note that in contrast to the code you have tried, the differences are that:
- It is the parent component (i.e. the consuming component) that is responsible for dictating what kind of markup to pass to the child
- The child component is as dumb as it gets: it simply receives markup and renders it in the
<slot>
element
See proof-of-concept below:
var customComponent = Vue.component('custom-component', {
template: '#custom-component-template'
});
new Vue({
el: '#app',
data: {
customHTML: null
},
components: {
customComponent: customComponent
},
methods: {
updateSlot: function() {
this.customHTML = '<p>Foo bar baz</p>';
}
}
});
.custom-component {
background-color: yellow;
border: 1px solid #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<h1>I am the app</h1>
<button type="button" @click="updateSlot">Click me to update slot content</button>
<custom-component>
<div v-if="customHTML" v-html="customHTML">
</div>
<div v-else>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</custom-component>
</div>
<!-- custom-component template -->
<script type="text/template" id="custom-component-template">
<div class="custom-component">
<h2>I am a custom component</h2>
<!-- slot receives markup set in <custom-component> -->
<slot></slot>
</div>
</script>
<component><template v-html="yourHtml"></template></component>
– Sphinx