【问题标题】:Show component only after all images loaded仅在加载所有图像后显示组件
【发布时间】:2021-08-18 10:49:36
【问题描述】:

我正在使用 Vue 3,我想要实现的是将所有图像加载到卡片(相册卡片)中,然后才在屏幕上显示组件。 下面是它现在的样子以及我的代码。

有人知道如何实现这一目标吗?

目前组件先显示再加载图片,这似乎不是一个完美的用户体验。 example

<template>
  <div class="content-container">
    <div v-if="isLoading" style="width: 100%">LOADING</div>
    <album-card
      v-for="album in this.albums"
      :key="album.id"
      :albumTitle="album.title"
      :albumId="album.id"
      :albumPhotos="album.thumbnailPhotos.map((photo) => photo)"
    ></album-card>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import albumCard from "@/components/AlbumCard.vue";

interface Album {
  userId: number;
  id: number;
  title: string;
  thumbnailPhotos: Array<Photo>;
}

interface Photo {
  albumId: number;
  id: number;
  title: string;
  url: string;
  thumbnailUrl: string;
}

export default defineComponent({
  name: "Albums",
  components: {
    albumCard,
  },
  data() {
    return {
      albums: [] as Album[],
      isLoading: false as Boolean,
    };
  },
  methods: {
    async getAlbums() {
      this.isLoading = true;
      let id_param = this.$route.params.id;
      fetch(
        `https://jsonplaceholder.typicode.com/albums/${
          id_param === undefined ? "" : "?userId=" + id_param
        }`
      )
        .then((response) => response.json())
        .then((response: Album[]) => {
          //api returns array, loop needed
          response.forEach((album: Album) => {
            this.getRandomPhotos(album.id).then((response: Photo[]) => {
              album.thumbnailPhotos = response;
              this.albums.push(album);
            });
          });
        })
        .then(() => {
          this.isLoading = false;
        });
    },
    getRandomPhotos(albumId: number): Promise<Photo[]> {
      var promise = fetch(
        `https://jsonplaceholder.typicode.com/photos?albumId=${albumId}`
      )
        .then((response) => response.json())
        .then((response: Photo[]) => {
          const shuffled = this.shuffleArray(response);
          return shuffled.splice(0, 3);
        });

      return promise;
    },
    /*
     Durstenfeld shuffle by stackoverflow answer: 
     https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array/12646864#12646864
    */
    shuffleArray(array: Photo[]): Photo[] {
      for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
      }
      return array;
    },
  },
  created: function () {
    this.getAlbums();
  },
});
</script>

【问题讨论】:

  • Suspense 可能就是您要找的...
  • @MichalLevý 感谢您的建议,但我使用不同的方法解决了这个问题,请参阅答案

标签: image vue.js


【解决方案1】:

我为解决这个问题所做的是在专辑卡组件内的 (img) html 标记上使用加载事件函数。加载图像时,会显示加载微调器。加载三张图片后,在屏幕上显示组件。

<template>
  <router-link
    class="router-link"
    @click="selectAlbum(albumsId)"
    :to="{ name: 'Photos', params: { albumId: albumsId } }"
  >
    <div class="album-card-container" v-show="this.numLoaded == 3">
      <div class="photos-container">
        <img
          v-for="photo in this.thumbnailPhotos()"
          :key="photo.id"
          :src="photo.thumbnailUrl"
          @load="loaded()"
        />
      </div>
      <span>
        {{ albumTitle }}
      </span>
    </div>
    <div v-if="this.numLoaded != 3" class="album-card-container">
      <the-loader></the-loader>
    </div>
  </router-link>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { store } from "@/store";
export default defineComponent({
  name: "album-card",
  props: {
    albumTitle: String,
    albumsId: Number,
  },
  data: function () {
    return {
      store: store,
      numLoaded: 0,
    };
  },
  methods: {
    thumbnailPhotos() {
      return this.$attrs.albumPhotos;
    },
    selectAlbum(value: string) {
      this.store.selectedAlbum = value;
    },
    loaded() {
      this.numLoaded = this.numLoaded + 1;
    },
  },
});
</script>

使用这种方法的重要说明是在 div 上使用 v-show 而不是 v-if。 v-show 将元素放入 html(并设置 display:none),而 v-if 不会在 html 中呈现元素,因此永远不会加载图像。

【讨论】:

    猜你喜欢
    • 2015-11-11
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2018-04-23
    • 1970-01-01
    • 1970-01-01
    • 2014-10-19
    • 2021-06-01
    相关资源
    最近更新 更多