можно ли использовать 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>

Есть три вещи, которые я пробовал до сих пор.

  1. поместите новый 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 раз. Однако другие картинки вообще не будут работать, а откроется новая вкладка.

  1. поместите новый 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>

В этом случае новая вкладка открывается всякий раз, когда нажимается фотография, что означает, что люминесценция не работает.

  1. не монтируется, но добавляет событие щелчка в этот компонент.

Например...

      <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/ я думаю, что может возникнуть проблема, когда код фактически не находит элементы изображения и, следовательно, ничего не предоставляет вызов. Возможно, вы могли бы попробовать отладить это, чтобы найти свою проблему.

Другие вопросы по тегам