I am trying to create photo website with vue.js and Laravel, and use luminous to magnify the photo when it is clicked. My photos are stored in AWS S3 bucket.
My vue.js structure is like below.
1.PhotoComponent.vue
- this component is literally rendering each photo.
<template>
<div class="photo">
<a class="luminous" :href="item.url">
<img class="photo_image" :src="item.url" :alt="`photo taken by ~~`">
</a>
</div>
</template>
<script>
export default {
name: "PhotoComponent.vue",
props: {
item: { // this item has photo info(like url)
type: Object,
required: true
}
},
}
</script>
<style scoped>
</style>
2.PhotoListComponent.vue
- this component is making a list of PhotoComponent.vue.
<template>
<div class="photo-list">
<div class="grid">
<PhotoComponent
class="grid_item"
v-for="photo in photos"
:key="photo.id"
:item="photo"
></PhotoComponent>
</div>
<PaginateComponent :current-page="currentPage" :last-page="lastPage"></PaginateComponent>
</div>
</template>
<script>
import {OK} from '../util';
import PhotoComponent from "./PhotoComponent";
import PaginateComponent from "./PaginateComponent";
export default {
name: "PhotoListComponent.vue",
components: {
PhotoComponent,
PaginateComponent
},
props: {
page: {
type: Number,
required: false,
default: 1,
}
},
data() {
return {
photos: [],
currentPage: 0,
lastPage: 0
}
},
methods: {
async fetchPhotos() { // I get each photo information through this method.
const response = await axios.get(`/api/photos/?page=${this.page}`);
if (response.status !== OK) {
this.$store.commit('error/setCode', response.status);
return false;
}
this.photos = response.data.data;
this.currentPage = response.data.current_page;
this.lastPage = response.data.last_page;
},
},
watch: {
$route: {
async handler() {
await this.fetchPhotos();
},
immediate: true,
}
},
}
</script>
<style scoped>
</style>
There are three things that I have tried so far.
- put new Luminous() in PhotoComponent, and put the function in mounted section.
<template>
<div class="photo">
<a class="luminous" :href="item.url">
<img class="photo_image" :src="item.url" :alt="`photo taken by ~~`">
</a>
</div>
</template>
<script>
import { Luminous } from 'luminous-lightbox';
export default {
name: "PhotoComponent.vue",
props: {
item: { // this item has photo info(like url)
type: Object,
required: true
}
},
methods: {
luminous() {
new Luminous(document.querySelector(".luminous"));
}
},
mounted: {
this.luminous();
}
}
</script>
In this case, first picture works, but "" opens as many as PhotoComponent.vue. For example, if I make a list of 9 pictures in PhotoListComponent and click the first photo, "" opens 9 times. However, other pictures won't work at all, but the new tab opens.
- put new LuminousGallery() in PhotoListComponent, and put the function in mounted section.
<template>
<div class="photo-list">
<div class="grid">
<PhotoComponent
class="grid_item"
v-for="photo in photos"
:key="photo.id"
:item="photo"
></PhotoComponent>
</div>
<PaginateComponent :current-page="currentPage" :last-page="lastPage"></PaginateComponent>
</div>
</template>
<script>
import {OK} from '../util';
import PhotoComponent from "./PhotoComponent";
import PaginateComponent from "./PaginateComponent";
import {LuminousGallery} from 'luminous-lightbox';
export default {
name: "PhotoListComponent.vue",
components: {
PhotoComponent,
PaginateComponent
},
props: {
page: {
type: Number,
required: false,
default: 1,
}
},
data() {
return {
photos: [],
currentPage: 0,
lastPage: 0
}
},
methods: {
async fetchPhotos() { // I get each photo information through this method.
const response = await axios.get(`/api/photos/?page=${this.page}`);
if (response.status !== OK) {
this.$store.commit('error/setCode', response.status);
return false;
}
this.photos = response.data.data;
this.currentPage = response.data.current_page;
this.lastPage = response.data.last_page;
},
luminous() {
new LuminousGallery(document.querySelectorAll('.luminous'));
},
},
watch: {
$route: {
async handler() {
await this.fetchPhotos();
},
immediate: true,
}
},
mounted: {
this.luminous();
}.
}
</script>
In this case, a new tab opens whenever the photo is clicked, which means that luminous does not work.
- not mounted, but add click event in those component.
For example...
<template>
<div class="photo">
<a class="luminous" :href="item.url" @click.prevent="luminous">
<img class="photo_image" :src="item.url" :alt="`photo taken by ~~`">
</a>
</div>
</template>
<script>
import { Luminous } from 'luminous-lightbox';
export default {
name: "PhotoComponent.vue",
props: {
item: { // this item has photo info(like url)
type: Object,
required: true
}
},
methods: {
luminous() {
new Luminous(document.querySelector(".luminous"));
}
},
}
</script>
In this case, the result is almost the same as pattern 1, but the first picture works perfectly as I expected. However, the other picutures won't open anything even a new tab.
Sorry for ranting. I am stuck with this problem for a week. I really need someone's help. Thank you for your cooperation.