Vue3+vite 项目中动态引入图片(非 public 目录)
今天在做项目的时候,使用动态路由配置,发现在 vue3+vite
项目中,动态引入图片,在开发环境中的时候,图片可以正常显示,但是打包构建后,部署生产找不到图片的,经过一番搜索,找到了解决方法,如下:
首先模版中的代码:
<template>
<div class="eggs-con">
<router-link
v-for="(dataEgg, index) in dataEggs"
:key="dataEgg.id"
:to="{ name: 'eggs', params: { eggType: dataEgg.type } }"
>
{{ dataEgg.name }}
<el-divider v-if="index !== dataEggs.length - 1" direction="vertical" />
</router-link>
<div v-if="!dataEgg">
<h1>查无此蛋</h1>
</div>
<div v-else>
<h1>{{ dataEgg.name }}</h1>
<p>{{ dataEgg.description }}</p>
<p>{{ dataEgg.flavour }}</p>
<!-- 开发环境可以正常的显示,打包后无法正常预览 -->
<img :src="`../../src/assets/images/${dataEgg.image}`" alt="" />
<h2>import.meta.glob (动态导入)</h2>
<img :src="imageSrc" v-if="imageSrc" />
<br />
<!-- <img :src="picture.default" alt=""> -->
<h2>使用计算属性方式:(new URL)</h2>
<img :src="imageSrcCom" alt="" />
</div>
</div>
</template>
之前用 vue2 版本的时候,使用的是require
来引入图片,打包构建工具是webpack
,但是现在使用的是vite
构建,所以需要使用import.meta.glob
来引入图片,并且需要使用new URL
来获取图片的路径. vite
和 webpack
的核心差别还是挺大的,在 vite
中并没有这样的包。
开发环境截图
glob 导入 动态引入图片
Vite 支持使用特殊的 import.meta.glob
函数从文件系统导入多个模块(该方式为异步加载模块形式),该函数接收一个匹配模块文件的通配符,返回一个对象,其中键是文件路径,值是可以导入相应模块的函数。
其中,data.json 文件中的内容如下:
[
{
"id": 1,
"name": "鸡蛋",
"type": "chicken-egg",
"image": "chicken-egg.jpeg",
"description": "又名鸡卵、鸡子,是母鸡所产的卵",
"flavour": "味甘,性平,无毒(煮熟后)"
},
{
"id": 2,
"name": "鸭蛋",
"type": "duck-egg",
"image": "duck-egg.jpeg",
"description": "又名鸭子、鸭卵、太平、鸭春、青皮等,为鸭科动物家鸭的卵,受精卵可孵化成小鸭",
"flavour": "性涼、味甘"
},
{
"id": 3,
"name": "鹅蛋",
"type": "goose-egg",
"image": "goose-egg.jpeg",
"description": "家禽鹅生下的卵",
"flavour": "有些油"
},
{
"id": 4,
"name": "鹌鹑蛋",
"type": "quail-egg",
"image": "quail-egg.jpeg",
"description": "鵪鶉所產的卵,蛋殼表面帶有棕褐色斑點",
"flavour": "味甘、性平"
},
{
"id": 5,
"name": "笨蛋",
"type": "dumb-egg",
"image": "dumb-egg.jpeg",
"description": "我才不是笨蛋",
"flavour": "没吃过"
}
]
生产环境截图
逻辑部分 JS 代码(setup 语法糖)
import { ref, computed, watch, watchEffect } from 'vue';
import dataEggs from '../src/data.json';
const imageSrc = ref('');
const eggType = computed(() => route.params.eggType);
const dataEgg = computed(() =>
dataEggs.find((egg) => egg.type === eggType.value)
);
// 方式1: // 使用 import.meta.glob 动态导入图片 不配置 { eager: true }
const images = import.meta.glob('../src/assets/images/*.jpeg');
watchEffect(async () => {
if (dataEgg.value && dataEgg.value.image) {
const imagePath = `../src/assets/images/${dataEgg.value.image}`;
const imageModule = images[imagePath];
if (imageModule) {
try {
const img = await imageModule();
imageSrc.value = img.default;
} catch (error) {
console.error('Image not found:', dataEgg.value.image, error);
imageSrc.value = '';
}
} else {
console.error('Image not found:', dataEgg.value.image);
imageSrc.value = '';
}
} else {
imageSrc.value = '';
}
});
以上这种方式匹配到的文件默认是懒加载
的, 通过动态导入
实现,并会在构建时分离为独立的 chunk 文件
。如果你倾向于直接引入(同步加载使用)所有的模块,你可以传入 { eager: true }
作为第二个参数`.
// ...
// 省略导入相关文件
// 方式1: // 使用 import.meta.glob 动态导入图片 配置 { eager: true }
const images = import.meta.glob('../src/assets/images/*.jpeg', { eager: true });
watchEffect(() => {
if (dataEgg.value && dataEgg.value.image) {
const imagePath = `../src/assets/images/${dataEgg.value.image}`;
const imageModule = images[imagePath];
if (imageModule) {
// console.log('imageModule.default', imageModule.default);
imageSrc.value = imageModule.default;
} else {
console.error('Image not found:', dataEgg.value.image);
imageSrc.value = '';
}
} else {
imageSrc.value = '';
}
});
使用 new URL() 的方法进行动态导入
在 Vue 中,如果你需要使用动态导入图片,你可以使用 new URL()
方法来获取图片的路径。
// ...
// 省略导入相关文件
const imageSrcCom = computed(() => {
if (dataEgg.value && dataEgg.value.image) {
try {
return new URL(
`../src/assets/images/${dataEgg.value.image}`,
import.meta.url
).href;
} catch (e) {
console.error('Image not found:', e);
return '';
}
}
return '';
});
在 new URL()
方法中,import.meta.url
是一个特殊的变量,它表示当前模块的 URL。 在 vue3+vite
的项目中,如果需要动态的导入图片,可以使用上面介绍的方法,防止在开发环境中好好的,打包构建后,部署到生产环境,图片无法正常预览...
Comments
请在后台配置评论类型和相关的值。