要引入一张文件名为动态的本地图片
原来使用vue-cli 或者 webpack 构建的vue程序 使用require就可以很好的解决
<div v-for="(item, index) in array">
<img :src="require(`@/assets/icon/${index}.png`)" />
</div>
但是require这个东西是webpack环境才会有
于是查看vite静态资源处理
以及各种技术论坛博客 提到的最多的就是 new URL()
这种方式
文章中提到 通过相对路径我们就能得到一个被完整解析的静态资源URL
于是乎更改代码如下:
<div v-for="(item, index) in array">
<img :src="getImageUrl(`${index}`)" />
</div>
function getImageUrl(name) {
return new URL(`../../assets/icon/${name}.png`, import.meta.url).href
}
开发环境可以正常显示
但是打包后发现这几张图片根本没有进行打包,导致加载图片报错404
再次查看文档,发现有这么一段话
也就是说必须保证字符串是静态的。当然写大量的switch是可以解决的, 或者可以把图片放到public文件夹下
下面就说一下我的解决办法。
既然上面几种办法行不通,那我就试着把所有图片当成模块全部导入
import icon_1 from '@/assets/icon/1.png'
import icon_2 from '@/assets/icon/2.png'
// more
const images = {
icon_1,
icon_2
// more
}
<div v-for="(item, index) in array">
<img :src="images[`icon_${index}`]" />
</div>
然后打包, 发现icon全部打包进来了。
但是这样做有点傻有100张icon就要导入100次,有没有什么比较方便的api可以一次性导入某个文件夹下的所有图片呢?
const modules = import.meta.glob('./dir/*.js')
// 编译后变成
const modules = {
'./dir/foo.js': () => import('./dir/foo.js'),
'./dir/bar.js': () => import('./dir/bar.js'),
}
看的出来所有模块都是异步模块, 继续看文档发现有个globEager
const modules = import.meta.globEager('./dir/*.js')
// 编译后变成
import * as __glob__0_0 from './dir/foo.js'
import * as __glob__0_1 from './dir/bar.js'
const modules = {
'./dir/foo.js': __glob__0_0,
'./dir/bar.js': __glob__0_1
}
正好满足需求,于是改造代码
const modules = import.meta.glob('/src/assets/icon/*') // 这里可以写 @ (路径别名) 或者 /src (绝对或相对路径)
const icons = (name) => {
const path = '/src/assets/icon/${name}.png' // 这里不可以写路径别名,只可以写绝对或者相对路已经
return modules[path]?.default
}
<div v-for="(item, index) in array">
<img :src="icons(index)" />
</div>
编译打包,完美
另外: import.meta.globEager
在vite v3 已经弃用 可以使用选项{ eager: true }
实现此功能
import.meta.glob('*', { eager: true })