I am using VueJS 2.5.3 on a section (not SPA) of a blog backend that makes an API call to check for a featured image attached to the post.
If it finds one, it uses a child component to show the image. The problem is that the child component isn't rendering after the API call is successful and so neither is the image object passed to it.
As you can see in this GIF, the child component isn't rendering <!---->
, I have a v-if
on it to check if the image exists. However, if I click on the child component inside of Vue DevTools, the child component renders and shows the image as expected.
My question is why would a child component only render after clicking on it in Vue Devtools? Does Vue Devtools trigger some sort of an event when you click on a component?
Here is the child component:
<template>
<div v-if="showImage" class="featured-image-container" :class="[ size ]">
<img :src="processedSrc" alt="Featured Image">
</div>
</template>
<script>
export default {
props: {
image: {
type: Object
},
size: {
type: String,
required: true
}
},
data () {
return {
showImage: false
}
},
computed: {
processedSrc: function () {
if (this.image && typeof this.image === 'object') {
this.showImage = true
return this.image.sizes[this.size].file
} else {
this.showImage = false
}
}
}
}
</script>
And here is a link to the code for the parent and child components:
The issue is in your PostFeaturedImage.vue
component. You are depending on a computed value processedSrc
to set a data property showImage
.
However, showImage
is initially false
and you are using it in the v-if
directive on the root element. This means that Vue will not render that element or the <img>
element inside of it.
Computed properties in Vue are lazy-loaded, meaning their functions are not called until they are referenced. Since the processedSrc
computed property is only being referenced on the <img>
element (and since that element is not being rendered) its method is not getting called, meaning the showImage
property is never set to true
.
However, when you inspect a component in Vue DevTools, it lists all of the computed properties, meaning that the method for the processedSrc
computed is getting called, and the showImage
property is being set in that case.
The easiest solution to your issue would be to use v-show
instead of v-if
, since elements inside a v-show
will be hidden but still rendered even if the value is false
.
However, I would almost never recommend setting a data property's value based on logic within a function for a computed property. It creates unintended, hard-to-debug side-effects which lead to issues like the one you're currently experiencing.
I would suggest making your showImage
property a computed property as well, based on the logic currently determining its value in the processedSrc
computed method. Then, you can determine whether or not to try to calculate the value of the processedSrc
computed based on the value of showImage
.
computed: {
showImage: function() {
return this.image && typeof this.image === 'object';
},
processedSrc: function () {
if (this.showImage) {
return this.image.sizes[this.size].file;
}
}
}
This way, it is much easier to see what is affecting what and your code will be easier to maintain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With