можно ли использовать luminous в Vue.js ?

#javascript #vue.js #vuejs2 #imgix #imgix-js

#javascript #vue.js #vuejs2 #imgix #imgix-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. поместите new Luminous() в PhotoComponent и поместите функцию в раздел mounted.
 <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.

  1. 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>
 

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

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

Комментарии:

1. Спасибо за ваш комментарий. На самом деле, я попробовал то, что вы предложили, и это работает отлично. Ты сделал мой день. Еще раз спасибо. @fred