Reputation: 665
I'm trying to create a simple gallery component where if you click on some image a Light-Box will appear where you can see full size photo and have options like next and previous photo or close the Light-Box.
Currently When I need to change the image to next or previous I change the src of the img-tag and it works.
Here comes my problem. I want to lazy load my images. I use lazysizes in my project. So the simple implementation to have an image to load is to add the class "lazyload" and to pass the property data-src instead of src.
However if I change to data-src my methods for next and previous image are not working.
< script >
export default {
props: {
data: {
type: Array,
required: true,
},
},
data: () => ({
visible: false,
currentImage: 0,
}),
methods: {
Toggle(index) {
this.currentImage = index
this.visible = !this.visible
},
Next() {
if (this.currentImage !== this.data.length - 1) this.currentImage++
},
Prev() {
if (this.currentImage !== 0) this.currentImage--
},
},
} <
/script>
<template>
<div id="gallery" class="gallery">
<!-- images grid -->
<div v-for="(item, i) in data" :key="'gallery-image' + i" class="image">
<img :src="item.image.thumbnail.url" @click.native="Toggle(i)" class="lazyload"/>
</div>
<!-- image lighbox on click -->
<div v-if="visible" class="lightbox">
<Icon class="cancel" @click="Toggle()"/>
<Icon name="left" :class="{ disable: currentImage == 0 }" @click="Prev()"/>
<img :src="data[currentImage].image.url" class="lazyload"/>
<Icon name="right" :class="{ disable: currentImage == data.length - 1 }" @click="Next()"/>
</div>
</div>
</template>
UPDATE I forgot to add crucial code. To implement lazysizes in a Nuxt project we need to add in nuxt.config.js the fallowing code. You can read more here.
build: {
extend(config, { isClient, loaders: { vue } }) {
vue.transformAssetUrls.img = ['data-src', 'src']
},
},
As I investigate in the developer tools I found that when triggering click for method like Next image, the src of the image does not change, only the data-src. I'm guessing I need a way to trigger this transform so that everything can work as expected.
Upvotes: 1
Views: 2359
Reputation: 665
Probably this is not the most elegant way to do it . I force re-render to my image component. You need to assign a key value to component and whenever the value changes a new instance creates of the component.
Upvotes: 0
Reputation: 46612
Also, on top of my comment, I do recommend looking into the official nuxt image module which do have native lazy loading out of the box: https://image.nuxtjs.org/components/nuxt-img
You could maybe combo this with some simple lightbox that does the trick for you. I've used vue-silentbox before, it is working pretty well.
You can have that kind of code there
<silent-box :gallery="photosToDisplay">
<template #silentbox-item="{ silentboxItem }">
<img :src="silentboxItem.src" :key="silentboxItem.id" />
</template>
</silent-box>
So, I guess that you could totally swap img
by a nuxt-img
there, and have it lazy-loaded.
The images are not lazy-loaded in the project, but here is a small project that I did to try out the lightbox if you want to quickly look how it renders (URL in the top right corner).
Upvotes: 1