vite项目中引入静态图片资源失败

317 阅读1分钟

问题描述

  • 在使用vite的vue3项目使用了动态访问静态资源,代码如下
  • 即给swiper-slide盒子动态添加背景图片,动态渲染页面
  <div class="main">
    <div class="swiper-wrapper">
      <Swiper
        :modules="[Pagination, Navigation, Autoplay]"
        :pagination="{ clickable: true }"
        loop
        :autoplay="{ delay: 3000 }"
        :slides-per-view="1"
      >
        <Swiper-slide
          class="swiper-slide"
          v-for="item in slides"
          :key="item.img"
          :style="{ backgroundImage: `url(${item.img})` }"
        >
        </Swiper-slide>
      </Swiper>
    </div>
    <div class="menu"></div>
  </div>

问题表现

发现这个图片是加载不出来的,路径是没问题的

image.png

然后打包这个项目,发现打包出来的文件也没有存在在打包目录中

image.png

原因分析

  • Vite 是一个在编译时运行的工具,因此它在构建过程中会静态地解析和处理资源。
  • 如果在代码中使用动态绑定静态资源(如使用变量拼接路径或通过动态表达式导入资源),Vite 在编译时无法解析这些路径,因此这些资源不会被正确地识别、处理或打包。
  • 只有显式的动态资源才会被认为是依赖,并在构建时处理

解决方案

1. 使用import方式导入图片

<script setup>
  import { Swiper, SwiperSlide } from "swiper/vue";
  import { Navigation, Pagination, Autoplay } from "swiper/modules";
  import banner1 from "@/assets/swiper/banner_s3.jpg";
  import banner2 from "@/assets/swiper/chequedeposit_s.jpg";
  import banner3 from "@/assets/swiper/iGTB Mobile Token.jpg";
  import banner4 from "@/assets/swiper/igtb_topbanner.jpg";
  import banner5 from "@/assets/swiper/iGTBTopBanner_SC.jpg";
  import banner6 from "@/assets/swiper/iGTB_banner_api.jpg";
  const slides = [
    {
      img: banner1,
      title: "1",
    },
    {
      img: banner2,
      title: "2",
    },
    {
      img: banner3,
      title: "3",
    },
    {
      img: banner4,
      title: "4",
    },
    {
      img: banner5,
      title: "5",
    },
    {
      img: banner6,
      title: "6",
    },
  ];
</script>
  <template>
  <div class="main">
    <div class="swiper-wrapper">
      <Swiper
        :modules="[Pagination, Navigation, Autoplay]"
        :pagination="{ clickable: true }"
        loop
        :autoplay="{ delay: 3000 }"
        :slides-per-view="1"
      >
        <Swiper-slide
          class="swiper-slide"
          v-for="item in slides"
          :key="item.img"
          :style="{ backgroundImage: `url(${item.img})` }"
        >
        </Swiper-slide>
      </Swiper>
    </div>
    <div class="menu"></div>
  </div>
</template>

2. 使用new URL方式加载图片

<script setup>
  import { Swiper, SwiperSlide } from "swiper/vue";
  import { Navigation, Pagination, Autoplay } from "swiper/modules";

  const slides = [
    {
      img: new URL("@/assets/swiper/banner_s3.jpg", import.meta.url),
      title: "1",
    },
    {
      img: new URL("@/assets/swiper/chequedeposit_s.jpg", import.meta.url),
      title: "2",
    },
    {
      img: new URL("@/assets/swiper/iGTB Mobile Token.jpg", import.meta.url),
      title: "3",
    },
    {
       img: new URL("@/assets/swiper/igtb_topbanner.jpg", import.meta.url),
      title: "4",
    },
    {
       img: new URL("@/assets/swiper/iGTBTopBanner_SC.jpg", import.meta.url),
      title: "5",
    },
    {
       img: new URL("@/assets/swiper/iGTB_banner_api.jpg", import.meta.url),
      title: "6",
    },
  ];
</script>
  <template>
  <div class="main">
    <div class="swiper-wrapper">
      <Swiper
        :modules="[Pagination, Navigation, Autoplay]"
        :pagination="{ clickable: true }"
        loop
        :autoplay="{ delay: 3000 }"
        :slides-per-view="1"
      >
        <Swiper-slide
          class="swiper-slide"
          v-for="item in slides"
          :key="item.img"
          :style="{ backgroundImage: `url(${item.img})` }"
        >
        </Swiper-slide>
      </Swiper>
    </div>
    <div class="menu"></div>
  </div>
</template>

3.public

直接将资源放在public里面

4.使用import()

 import("@/assets/swiper/iGTB_banner_api.jpg").then((res) => {
    console.log("res", res.default);
    url.value = res.default;
  });