As far as I understand Vue 2+, a component should be re-rendered when the slot content changes. In my case I had an error-message
component that should hide until it has some slot content to show. At first I had this method attached to v-if
on my component's root element (a computed
property won't work, Vue doesn't appear to have reactivity on this.$slots
).
checkForSlotContent() {
let checkForContent = (hasContent, node) => {
return hasContent || node.tag || (node.text && node.text.trim());
}
return this.$slots.default && this.$slots.default.reduce(checkForContent, false);
},
This works well whenever 99% of changes happen in the slot, including any addition or removal of DOM elements. The only edge case was usage like this:
<error-message> {{someErrorStringVariable}} </error-message>
Only a text node is being updated here, and for reasons still unclear to me, my method wouldn't fire. I fixed this case by hooking into beforeUpdate()
and created()
, leaving me with this for a full solution:
<script>
export default {
data() {
return {
hasSlotContent: false,
}
},
methods: {
checkForSlotContent() {
let checkForContent = (hasContent, node) => {
return hasContent || node.tag || (node.text && node.text.trim());
}
return this.$slots.default && this.$slots.default.reduce(checkForContent, false);
},
},
beforeUpdate() {
this.hasSlotContent = this.checkForSlotContent();
},
created() {
this.hasSlotContent = this.checkForSlotContent();
}
};
</script>