Skip to content

图片组件

图片组件展示

景色图片均通过 AI 生成

图片组件展示
这张图片害羞了
图片组件展示
html
<PicViewer
  title="图片组件展示"
  src="/assets/components/scenery-1.jpg"
></PicViewer>

vite 对图片加载引用的介绍

首先 vite 在图片资源的处理上有一些不同于 webpack,在 webpack 中常用的 requirevite 中不存在。

所以在这里简单介绍一下 vite 图片资源引用的问题。

首先图片资源的引用有相对路径绝对路径之分,还有打包前打包后增加文件指纹之分。

路径问题先上一些图片位置图

文件位置图
该位置位于public/assets文件目录下,该文件的资源将不会被增加文件指纹
该位置位于public/assets文件目录下,该文件的资源将不会被增加文件指纹
文件位置图
该位置位于当前文件目录下,该文件的资源将会增加文件指纹
该位置位于当前文件目录下,该文件的资源将会增加文件指纹

以下是图片资源引用的情况

第一种 - 静态引入

使用地址是 public 文件夹(静态资源路径/根地址路径)下的文件,结果

主要代码

  • 优点 开发生产环境都可以使用
  • 缺点 但是不是相对路径不能让图片文件放到随意文件夹
  • 缺点 而且没有图片指纹容易在更新文件时候导致资源不加载最新文件

因为直接使用静态资源路径,就等于直接访问图片,不经过打包所以不出问题

静态资源路径
根地址路径
根地址路径
调用代码展示
vue
<template>
  <PicViewer title="静态资源路径" src="/assets/components/scenery-2.jpg" alt="根地址路径"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// 静态资源路径
</script>

第二种 - 相对路径

直接使用相对路径

  • 缺点 开发生产图片都不展示,不可用

直接使用相对路径,组件声明位置文档展示位置不同,(受资源位置限制太大)
所以相对路径拿不到相应的文件所以展示不了

最简单的相对路径
这张图片害羞了
最简单的相对路径
调用代码展示
vue
<template>
  <PicViewer title="最简单的相对路径" src="./assets/scenery-1.jpg"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// 最简单的相对路径
</script>

第三种 - new URL(静态)

new URL 引入,new URL 是 vite 提供的静态资源引用方法

主要代码

javascript
const imageUrl = new URL("./assets/scenery-1.jpg", import.meta.url).href;
  • 缺点 开发环境没问题,生产环境刷新页面之后丢失
  • 优点 可以放在任意文件夹
  • 缺点 但是在加载的时候 必须显示的使用 new URL 引入资源 有点蠢

new URL(静态) 引入 会动态解析资源映射关系所以可以使用

new URL(静态) 引入
这张图片害羞了
new URL(静态) 引入
调用代码展示
vue
<template>
  <PicViewer title="new URL(静态) 引入" :src="imageUrl"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// new URL(静态) 引入
const imageUrl = new URL("./assets/scenery-1.jpg", import.meta.url).href;
</script>

第四种 - new URL(动态)

new URL 引入,new URL 是 vite 提供的静态资源引用方法

主要代码

javascript
const newURLAll = import.meta.glob([
  "./assets/*.jpg",
  "./assets/*.png",
  "./assets/*.gif",
]);
const imageMap: Map<string, string> = new Map();
for (const path in newURLAll) {
  // `${path}` 这里是动态的
  imageMap.set(path, new URL(`${path}`, import.meta.url).href);
}
  • 缺点 开发可以,但是生产不行
  • 优点 可以放在任意文件夹
  • 小优点 在加载的时候 可以使用循环方式引入图片资源

new URL(动态) 引入 使用变量来控制图片加载,vite 将不解析。

在生产构建时,Vite 才会进行必要的转换保证 URL 在打包和资源哈希后仍指向正确的地址。然而,这个 URL 字符串必须是静态的,这样才好分析。否则代码将被原样保留、因而在 build.target 不支持 import.meta.url 时会导致运行时错误。

vite 对于动态引入的解释

new URL(动态) 引入
这张图片害羞了
new URL(动态) 引入
调用代码展示
vue
<template>
  <PicViewer title="new URL(动态) 引入" :src="imageMap.get(`./assets/scenery-2.jpg`)"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// new URL(动态) 引入
const newURLAll = import.meta.glob(["./assets/scenery-2.jpg"]);
const imageMap: Map<string, string> = new Map();
for (const path in newURLAll) {
  // `${path}` 这里是动态的
  imageMap.set(path, new URL(`${path}`, import.meta.url).href);
}
</script>

第五种 - imageUrl 方法

imageUrl 方法 通过一个方法传值来进行图片调用 使用的还是 new URL 方法但是转换成半静态了

主要代码

javascript
const imageUrl = (url: string) => {
  // `./assets/${url}` 这个在vite的理解中是静态的
  const obj = new URL(`./assets/${url}`, import.meta.url);
  return obj.pathname;
};
  • 缺点 开发环境没问题,生产环境刷新页面之后丢失
  • 优点 可以放在任意文件夹
  • 优点 在加载的时候 只需要传一个文件名 但是限制了当前路径的 assets 文件夹

new URL 在 ./assets/${url} 代码中被理解成静态代码,所以进行资源映射处理。

imgUrl方法
这张图片害羞了
imgUrl方法
调用代码展示
vue
<template>
  <PicViewer title="imgUrl方法" :src="imageUrl('scenery-3.jpg')"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// imageUrl 方法
const imageUrl = (url: string) => {
  // `./assets/${url}` 这个在vite的理解中是静态的
  const obj = new URL(`./assets/${url}`, import.meta.url);
  return obj.pathname;
};
</script>

第六种 - import

import 引入

  • 优点 开发生产都可以使用图片,没问题
  • 优点 可以放在任意文件夹
  • 缺点 但是在加载的时候 必须显示的使用 import 引入资源 有点蠢

import 引入 会动态解析资源映射关系所以可以使用

import引入
这张图片害羞了
import引入
调用代码展示
vue
<template>
  <PicViewer title="import引入" :src="image"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// import引入
import image from "./assets/scenery-4.jpg";
</script>

第七种 - import.meta.glob

import.meta.glob 引入

  • 优点 开发生产都可以使用图片,没问题
  • 优点 可以放在任意文件夹
  • 优点 在加载的时候 可以使用一个导入方法加载完所有图片
javascript
import.meta.glob(["./assets/*.jpg", "./assets/*.png", "./assets/*.gif"], {
  eager: true,
  import: "default",
});

该语句是 vite 的资源引入语句 import.meta.glob

  • ["./assets/*.jpg", "./assets/*.png","./assets/*.gif"] : 匹配到的文件默认是懒加载的,通过动态导入实现,并会在构建时分离为独立的 chunk
  • eager: true : 直接引入所有的模块
  • import: "default" : import 为 default 可以加载默认导出
import.meta.glob 引入
这张图片害羞了
import.meta.glob 引入
调用代码展示
vue
<template>
  <PicViewer title="import.meta.glob 引入" :src="importMetaGlob[`./assets/scenery-5.jpg`]"></PicViewer>
</template>

<script lang="ts" setup>
import PicViewer from "./index.vue";
// import.meta.glob 引入
const importMetaGlob: Record<string, string> = import.meta.glob(
  ["./assets/scenery-5.jpg"],
  {
    eager: true,
    import: "default",
  }
);
</script>

总结

在 vite 静态资源引用中 单个文件引用使用 import 是最方便的,多个文件引用的话推荐使用 import.meta.glob 方法