Vite + Vue 中 img 动态设置 src

直接在模板中使用:

html 复制代码
<img src="@/assets/images/home/home_icon.png" />

如果设置动态 src:

html 复制代码
<img :src="`@/assets/images/home/${name}.png`" />

这样加载的路径就是:http://10.227.198.175:5173/pages/home/@/assets/images/home/home-icon.png 所以 @/assets 不能正确解析,src 当成字符串,按相对路径处理了。

导入图片,在模板中引用:

js 复制代码
<script setup lang="ts">
const name = ref('home_icon') // Just an example

const img = computed(() => require(`@/assets/images/home/${name.value}.png`))
</script>

<template>
<img :src="img" alt="img" />
</template>

报错:Uncaught ReferenceError: require is not defined

因为 Vite 是基于 ES Modules (ESM) 构建的,而 require 是 CommonJS 模块系统的一部分。

使用 new URL(url, import.meta.url)

看官网,使用这种方式处理静态资源:

js 复制代码
function handleSrc(name: string): string {
  const img = new URL(
    `../../../assets/images/home/${name}.png`,
    import.meta.url,
  ).href

  return img
}

<template>
<img :src="img" alt="img" />
</template>

i​mport.meta.urlURL 构造器 都属于原生的功能。

import.meta 打印出来:

url 就是当前的模块地址。

new URL 构造一个 url 对象,语法:

js 复制代码
new URL(url)
new URL(url, base)

如果 url 是一个相对路径,则必须提供 base,如果 url 是一个绝对路径,则 base 会被忽略。

而构造的对象为:

实际上以上构造的 url 必须是相对地址,官网也有说,一开始我使用 @/assets 的方式,也是不能正确解析:

js 复制代码
function handleSrc(name: string): string {
  const img = new URL(
    `@/assets/images/home/${name}.png`,
    import.meta.url,
  ).href

  return img
}

<template>
<img :src="img" alt="img" />
</template>

直接在 src 中使用相对地址

以上通过构造 url 的方式可行,实际上在 src 中直接使用相对路径就可以了:

html 复制代码
<img :src="`../../../assets/images/home/${name}.png`" />

总结:如何使用别名@

因此,以上 如果设置动态 src 的问题在于,别名 @ 的处理问题。

在 Vue 模板中,静态路径可以使用别名,例如 @。所以,<img src="@/assets/images/home/home_icon.png" /> 是有效的,因为 @/assets/images/home/home_icon.png 是一个静态的字符串,webpack 在编译时可以正确地解析它。这是因为在编译阶段,这些路径已经被明确定义,Vite 能够静态地找到并处理这些资源。

然而,当试图在动态字符串中(例如模板字符串或绑定的表达式)使用别名时。像这样的代码 <img :src="`@/assets/images/home/${name}.png`" /> 这个路径是在运行时被计算的,webpack 在编译阶段无法知道这个路径的最终值会是什么。因此,webpack 无法解析或处理这个路径引用的资源。

还可以使用 import()

js 复制代码
<template>
  <img :src="imgUrl" alt="Dynamic Image">
</template>

<script setup>
import { ref } from 'vue';

let name = 'your-image-name'; // 你的图片名
let imgUrl = ref('');

import(`@/assets/images/${name}.png`)
  .then(module => {
    imgUrl.value = module.default;
  });
</script>

import() 也是一个原生的功能。它是一个返回 Promise 的函数,可以在运行时动态加载模块。

但是这种方法依然无法处理别名。

相关推荐
掘金者阿豪1 小时前
在AI时代,没有人是“只写一行代码的人”——我们为何都在被迫成为全栈?
vue.js·后端
英俊潇洒美少年2 小时前
JS 事件循环(宏/微任务) ↔ Vue ↔ React** 三者的关系
javascript·vue.js·react.js
烈焰飞鸟2 小时前
iconfont 在 uni-app 项目中的完整使用指南
vue.js·uni-app·iconfont
533_2 小时前
[vue3] 动态引入本地静态资源(URL)
前端·javascript·vue.js
EF@蛐蛐堂3 小时前
【vue】新前端工具链Vite+ Alpha
前端·javascript·vue.js
SuperEugene4 小时前
Vue3 组合式函数(Hooks)封装规范实战:命名 / 输入输出 / 复用边界 + 避坑|Vue 组件与模板规范篇
开发语言·前端·javascript·vue.js·前端框架
英俊潇洒美少年4 小时前
Vue3 中 watch的 flush 选项(默认无/`post`/`sync`)的区别
前端·javascript·vue.js
凤山老林4 小时前
Js如何实现一个抽奖程序
前端·javascript·vue.js
踩着两条虫5 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十五):API与参考之Renderer API 参考
前端·vue.js·人工智能
踩着两条虫5 小时前
AI 驱动的 Vue3 应用开发平台 深入探究(二十四):API与参考之Provider API 参考
前端·vue.js·ai编程