DEV Community

Discussion on: Lazy Loading Images in Nuxt

Collapse
 
jeckojim profile image
jeckojim • Edited

Hi Saul,
After looking in a lot of example, I found your article really promising on the best way to implement it. Since then I try to apply it but with multiple "source" elements in a "picture" element. I was thinking doing with something like the folllowing but i'm a bit stuck (I'm not use to do this kind of computed manipulations):

// parent component where the component is called
<TheLazyResponsiveImage
    :imgId="'intro-hero-img'"
    :imgName="'intro-hero-image'"
    :imgSourceTypes="[webp, png]"
    :imgSourceTypeFallback="png"
    :srcsetSizes="{'943w':'944x640', '768w':'769x521', '511w': '512x347'}"
/>
//---------------
// TheLazyResponsiveImage.vue
<template>
//if there is imgSourceTypes prop, I use the<picture> element.
  <picture v-if="imgSourceTypes">
    <source
      v-for="imgSourceType in imgSourceTypes"
      :key="imgSourceType"
      :type="'image/' + imgSourceType"
      :srcset="srcset()"
    >
    <img
      :id="imgId"
      :src="src()"
      :alt="$t('brand_name') + ' ' + name"
      class="product-img is-block"
    >
  </picture>
// I would use your sources method just for regular <img> element
  <img v-else
    :class="{ lazyload: loading === 'lazy' && !supportsLoadingAttribute }"
    :loading="loading"
    v-bind="{ ...sources }"
  >...

//------
// Javascript
<script>
let supportsLoadingAttribute = false

if (process.client) {
  supportsLoadingAttribute = require('~/assets/js/supports/loading-attribute').default
}

export default {
  props: {
    imgId: {
      type: String,
      required: false,
      default: ''
    },
    imgName: {
      type: String,
      required: true,
      default: ''
    },
    imgSourceTypes: {
      type: Array,
      required: true,
      default () {}
    },
    imgSourceTypeFallback: {
      type: String,
      required: true,
      default: 'png'
    },
    srcsetSizes: {
      type: Object,
      required: true,
      default () {}
    },
    placeholder: {
      type: String,
      required: false,
      default: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='
    },
    alt: {
      type: String,
      required: false,
      default: ""
    },
    loading: {
      type: String,
      required: false,
      default: 'lazy'
    }
  },

  data () {
    return {
      supportsLoadingAttribute: false
    }
  },

  computed: {
    src () {
      return require(`@assets/img/${this.imgName}-${Object.keys(this.srcsetSizes)[0]}.${this.imgSourceTypeFallback}`)
    },
// this is where I'm not sure on how to proceed, I need to 
    srcset (imgType) {
      let dataSrcset = ''
      let srcsetSizesCounter = 0
      this.srcsetSizes.forEach((srcsetImgDimension, srcsetWidthKey) =­> {
        dataSrcset += `${require(`@assets/img/${this.imgName}-${srcsetImgDimension}.${imgType}`)} ${srcsetWidthKey}`
        srcsetSizesCounter++
      }
      return dataSrcset    
   }
// I would use your sources method just for regular <img> element
   ...
  },

  mounted () {
    this.supportsLoadingAttribute = supportsLoadingAttribute
  }
}

If you can guide me it will be great, if not I think I will try another way.
Maybe there is syntax errors in code but I just wanted to show the concept.
Thank you for your article again.

Collapse
 
saul profile image
Saul Hardman

Hi @jeckojim , for some reason DEV didn't alert me to your comment (perhaps because of how new your account is.)

I'll take a look at your example and get back to you as soon as possible with some suggestions – have a nice weekend 👋