通常情况下,我们写在css中的背景图,经过vite或者webpack的打包编译后会生成文件指纹信息
现在需求是这个图片需要动态变化(路径某部分需要动态替换)。
这时候有人会说通过style动态变量来实现,但是打包后运行发现他的路径是源代码下的路径,并不是打包后的路径,原因是 无论是vite还是webpack,他们要做的这种转换分析的是静态代码,你style写了个动态参数他得运行之后才能知道路径是什么的,vite和webpack需要的是运行之前的静态路径代码。 同理:v-bind,img元素src属性动态赋值。
又有人提出了解决办法,就是不把图片放在src下了,把他放在public下,因为我们知道vite、webpack在打包的时候,public目录是原封不动的。但是这样是有弊端的,就是没有文件指纹信息了,一旦下次打包图片内容替换了,由于没有文件指纹,名字是不会变的。而这种静态图片资源,用户那边会缓存很长一段时间,文件名没变,他就不会读取新的文件内容
第三种方法,通过watchEffect动态导入的方式
watchEffect(async()=>{
const module = await import(`./assets/img/${name}.jpg`) //这边要用模板字符串
console.log(module)
})
我们可以发现,打印结果就是打包之后的路径信息,原因是vite在分析的时候,发现你用了动态引入,同时使用了``模板字符串(vite会把模板字符串识别成js),这个模板字符串里有部分是动态变化的,所以vite干脆一不做二不休把这路径下所有后缀为jpg的图片全部生成了打包结果。这种方式可行是可行,但是他会平白无故打包出很多js文件,而且这还是异步的,所以不是特别好。最好是找一种同步的方式,同时不要生成这些一大堆js文件。
最后一种方法,也是最佳解决方法。就是通过浏览器自带的URL构造函数
const url = computed(()=> {
const obj = new URL(`./assets/${name.value}.jpg`,import.meta.url) //第一个参数必须用模板字符串,第二个参数是基准路径(就是打包之后的当前模板的路径)
return obj.pathname;
})
然后再把这个路径应用到style动态属性里去。这种实现方式有文件指纹,也不会生成一大堆js文件。