Situation&Task
列表渲染,需要根据列表每行item的type字段导入不同icon并渲染到页面
Action
一开始想要使用require动态导入图片的方式加载image
<div
:style="{
backgroundImage: `url(
${require(`./assets/${getFileIcon(item)}`)}
)`}">
</div>
...
getFileIcon(item) {
return 'image.png';
},
但是会报错
“require is not defined”
因为 Vite 是一个基于现代浏览器原生ES模块的开发服务器,并不支持使用 CommonJS(require导入)模块语法
所以我们需要另辟蹊径:使用 vite 提供的静态资源载入方法
import.meta.url是一个 ESM 的原生功能,会暴露当前模块的 URL。将它与原生的URL 构造器组合使用,在一个 JavaScript 模块中,通过相对路径我们就能得到一个被完整解析的静态资源 URL,同时也可以通过字符串模板支持动态 URL
-
import.meta
元属性将特定上下文的元数据暴露给 JavaScript 模块。它包含了这个模块的信息,例如这个模块的 URL。-
URL
接口用于解析,构造,规范化和编码URL。将 URL 指定为字符串或提供相对 URL 和基本 URL 来创建新的 URL 对象。然后,你可以轻松读取 URL 的已解析组成部分或对 URL 进行更改。
其中 URL 的 href 属性包含我们需要的数据:即完整 URL 字符串
<img
:src="getFileIconUrl(item)"
alt=""
/>
...
const getImageUrl = (item) => {
let name = name='test1.png';
if (name) {
return new URL(`./assets/${name}`, import.meta.url).href;
}
return new URL(`./assets/test2.png`, import.meta.url).href;
};
这样会出现新的问题
渲染出来的img标签内容不对,我们看到,引入的图片资源变成了undefined,继续排查原因
<img src="http://localhost:9999/undefined />
我们将模板字面量移动到一个变量中,然后再将路径和资源名拼接一起返回就可以解决这个问题
const getImageUrl = (item) => {
let name = name='test1.png';
if (name) {
const path = new URL('./assets/', import.meta.url);
return `${path}/${name}`;
}
return new URL(`./assets/test2.png`, import.meta.url).href;
};
Result
这样我们的图片就能顺利渲染出来了
Vite开发的项目中无法使用CommonJS模块语法,需要使用Vite本身提供的静态资源引入方式实现我们的需求