можно ли использовать luminous в Vue.js?
Я пытаюсь создать веб-сайт с фотографиями с vue.js и Laravel и использую luminous, чтобы увеличить фотографию при нажатии. Мои фотографии хранятся в корзине AWS S3.
Моя структура vue.js выглядит следующим образом.
1.PhotoComponent.vue
- этот компонент буквально рендерит каждую фотографию.
<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
- этот компонент составляет список 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>
Есть три вещи, которые я пробовал до сих пор.
- поместите новый Luminous() в PhotoComponent и поместите функцию в смонтированный раздел.
<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>
В этом случае работает первая картинка, но "" открывается столько же, сколько PhotoComponent.vue. Например, если я создаю список из 9 изображений в PhotoListComponent и нажимаю на первое фото, "" открывается 9 раз. Однако другие картинки вообще не будут работать, а откроется новая вкладка.
- поместите новый LuminousGallery() в PhotoListComponent и поместите функцию в смонтированный раздел.
<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>
В этом случае новая вкладка открывается всякий раз, когда нажимается фотография, что означает, что люминесценция не работает.
- не монтируется, но добавляет событие щелчка в этот компонент.
Например...
<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>
В этом случае результат почти такой же, как и у шаблона 1, но первая картинка работает идеально, как я и ожидал. Однако другие картинки ничего не откроют даже в новой вкладке.
Извините за разглагольствование. Я застрял с этой проблемой в течение недели. Мне очень нужна чья-то помощь. Спасибо за ваше сотрудничество.
1 ответ
Konnichiwa @wadakatu, здесь Фред из @imgix (сопровождающий Luminous).
Вы должны быть в состоянии заставить все ваши решения работать.
Для 1/ я думаю, вам нужно настроить таргетинг только на изображение, которое существует в этом компоненте, поэтому что-то вроде этого может работать:
<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() {
// only look for relevant elements *inside* this component. Should only match one element
new Luminous(this.$el.querySelector(".luminous"));
},
},
mounted() {
this.luminous();
},
};
</script>
Для 2/ я думаю, что может возникнуть проблема, когда код фактически не находит элементы изображения и, следовательно, ничего не предоставляет