Vue 图片资源路径问题
新手学习的笔记。
问题
web需要大量图片,图片来源大致分为这几个:
- 静态的
- 动态的
静态的应该是指类似 logo 之类的,用作页面修饰的图片。
动态的是指从服务器动态得到的(如博客图片每一篇都不一样,需要动态获取)。
写法大致分为这几个:
- 直接在img标签中书写
- 在data等域中书写,然后动态改变 img。
由于是新手,所以不从原理探究,而是了解用法。
其实最好的教程是 vue 的 hello world 页面,这个页面包含了 logo(动态图片)与 icon(静态图片),通过它们基本可以理解用法。
asserts 文件夹
仔细观察项目目录,分有 public 和 asserts 文件夹:
顾名思义,这两个文件夹应该管控资源。
首先从asserts开始。
初探
我们首先打开 App.vue
,查看template:
// src/App.vue
// 项目中的图片路径为
// src/assets/logo.png
里面定义了一个 Vue logo,其中引用了asserts文件夹的图片。根据路径,我们可以找到图片路径。那么如果我们有其他图片,自然也可以类比使用。
接下来我们看看在更高层目录(组件)中是否也可以通过这种方式使用:
// src/components/HelloWorld.vue
...
// 项目中的图片路径为
// src/assets/logo.png
上面我们在components
文件夹中使用,通过..
尝试使用asserts文件加下的logo图片,然后查看效果:
出现了两个 logo
图片,第一个是在 App.vue
中使用的,第二个是在我们的 hello world
组件中使用,符合预期。
那么类推,在任何位置的组件我们可以直接在 img
标签中使用 asserts
的图片标签。
这种方法应该是静态的,因为在Vue
中,我们不该使用 js
获取。
除去 img
标签,另一个十分重要的图片引入方法为通过 background-image
属性引用,试试看是否有效:
// src/components/HelloWorld.vue
...
// css
.height{
height: 200px;
width: 200px
}
我们定义了一个div
标签,占用 200x200空间,并让 background-image
引用与 img
标签相同的路径:
结果显示 div确实存在,但是背景图没有显示出来,怎么回事?
进一步
按下 F12
打开 dev tools
, 让我们检查下路径:
可以看到 img
标签的 src
变为了 /img/logo.82b9c7a5.png
, 而不是我们写入的 ../assets/logo.png
,而 div 的背景路径没有发生改变,导致无法显示正确的背景图片。
大致查阅了下资料, 发现
img
标签是通过webpack
的file-loader
处理过的,换句话说img
标签的路径会被webpack
转换,从而得到正确的引用。我的一个猜测是通过这种方法可以让资源路径更加容易理解,同时文件名称中包含哈希值,可以避免与public中的文件(之后叙述)冲突。
通过这种方式可以了解到:img
标签的路径会被正确转换,而 background-image
不会被转换。
举一反三,我们尝试在 data 中写入路径引用:
// src/components/HelloWorld.vue
// template
// script
data() {
return {
image: '../assets/logo.png',
}
}
那么这个img路径自然也不会被处理,从而无法显示。
public 文件夹
public 文件夹在项目根目录。
根据搜索到的资料, public 文件夹不会被 webpack
处理,你用什么路径引用他就是什么,那么原理上,我们可以在 img
,background-image
,data
中正确的引用它。
helloworld项目已经给了一个 public引用示例,那就是我们浏览器页面标签旁边的logo:
// public/index.html // 文件路径: // public//favicon.ico
为什么我们在
index.html
中寻找呢?因为所有 vue 组件都是以index.html
为模板进行修改的,在这里定义了我们的 icon。
可以看到,在这个文件夹下直接引用了favicon.ico
并且成功加载了。
类比,在我们的 helloworld
组件中使用:
(为了效果明显,我把logo在public文件夹下拷贝了一份)。
// src/components/HelloWorld.vue
// template
// script
data() {
return {
img: 'logo.png'
}
}
结果,asserts
引用与 public
引用都得到了正确的显示。
再结合之前对 asserts 的探究,通过在文件末尾添加哈希值,避免了public的命名冲突。
总结
因为是新手,所以只能从表观来理解,希望以后随着深入能从原理上理解。
asserts
文件夹下的资源会被 webpack
处理(添加哈希值等等),导致直接引用无法找到文件。
public
文件夹下的资源不会被处理,可以直接通过路径引用。
结合之前的需求(动态与静态资源),我总结了下面想法:
-
public
文件夹下存放前端需要的资源文件(如logo,动画需要图片等等)。为了正确使用,应该将该文件交给后端放入正确位置,从而得到正确引用。 - 一种很常见的需求是后端发送json包,包内包含图片路径,这时其实完全是后端问题,后端应该保证给的图片路径能被正确引用,与
public
,asserts
文件夹无关。 -
public, asserts
只是前端开发时使用的资源文件夹。一种需求是前端需要使用类似mock.js
等库进行后端数据模拟,为了得到正确的图片数据,应该将图片资源放入public中,并使用正确路径,在最后交付时删除测试文件。