Home > database >  Nuxt, Vuetify skeleton loader while image loads
Nuxt, Vuetify skeleton loader while image loads

Time:04-12

I cannot find one proper example of loading an image with a skeleton loader. I'm using nuxt Vuetify and I'm trying to use a simple image with a skeleton loader.

Here is my code.

<template>
  <v-skeleton-loader v-if="loading" :loading="loading" type="image">
    <v-card
      v-show="loaded"
      
      shaped
      color="darkgreen"
      width="500"
      flat
    >
      <v-img
        src="/products/em-lucky-combo.jpg"
        max-width="500"
        @load="hasLoaded"
      >
      </v-img>
    </v-card>
  </v-skeleton-loader>
</template>

my method

<script>
export default {
  methods: {
    hasLoaded() {
      console.log('Image finished loading')

      this.loading = false
      this.loaded = true
    },
  },
}
</script>

But as I said the method never gets called when it is inside the v-card tag or directly in the skeleton loader.

I have tried using @load, I have tried using mounted hooks like below.

<script>
export default {
  mounted() {
    const readyHandler = () => {
      if (document.readyState === 'complete') {
        console.log('Document Rendered')
        this.loading = false
        this.loaded = true
        document.removeEventListener('readystatechange', readyHandler)
      }
    }

    document.addEventListener('readystatechange', readyHandler)

    readyHandler() // in case the component has been instantiated lately after loading
  },
}
</script>

But nothing seems to work properly or elegantly. Is it just not possible? The moment the <v-img> tag is inside the skeleton loader or inside a v-card inside a skeleton loader it never gets rendered no matter what I do. One suggestion was to use a slot. I'm guessing it has something to do with slots but I do not understand how to use these.

I tried doing something like this.

<template v-slot:default>
  <v-card
    
    shaped
    color="darkgreen"
    width="500"
    transition="fade-transition"
    flat
  >
    <v-img
      src="/products/em-lucky-combo.jpg"
      max-width="500"
      transition="fade-transition"
      @load="imageLoaded"
    ></v-img>
  </v-card>
</template>

I tried using the code below.

How to make v-skeleton-loader inside v-for in vuetify?

<v-img>
  <template #placeholder>
    <v-sheet>
      <v-skeleton-loader />
    </v-sheet>
  </template>
</v-img>

CodePudding user response:

Thanks to @kissu I realised my approach was wrong and unnecessary . I ended up giving my images some set dimensions and using a lazy image loader with a placeholder slot which works just fine. As he mentioned my images are loaded locally so it wont really work in my case.

What I did in the end.

<template>
  <v-card  flat shaped width="500">
    <v-img
      aspect-ratio="1"
      
      lazy-src=""
      max-height="350"
      max-width="500"
      src="/"
      transition="fade-transition"
    >
      <template v-slot:placeholder>
        <v-row
          align="center"
          
          justify="center"
        >
          <v-progress-circular
            color="grey lighten-5"
            indeterminate
          ></v-progress-circular>
        </v-row>
      </template>
    </v-img>
  </v-card>
</template>

CodePudding user response:

At the end, OP had enough of using just some dimensions and a lazy loader image. Since images were local, there was no need for a skeleton.

<template>
  <v-card  flat shaped width="500">
    <v-img
      aspect-ratio="1"
      
      lazy-src=""
      max-height="350"
      max-width="500"
      src="/"
      transition="fade-transition"
    >
      <template v-slot:placeholder>
        <v-row
          align="center"
          
          justify="center"
        >
          <v-progress-circular
            color="grey lighten-5"
            indeterminate
          ></v-progress-circular>
        </v-row>
      </template>
    </v-img>
  </v-card>
</template>
  • Related