Vue 的圖片引入方式

前言

這邊稍微記錄一下該如何正確地在 Vue Cli 或 Vite 中引入圖片,因為這個問題其實很常見也很容易搞錯,所以就乾脆寫一篇記錄一下。

什麼是靜態資源與非靜態資源

往下介紹之前,我想先解釋一下何謂靜態資源與非靜態資源的意思

那麼由於後面我們會講到 Vue Cli,所以這邊就先以 Vue Cli 作為舉例說明這兩者差異。

Vue Cli 本身是基於 Webpack 所製作的,因此引入圖片必須區分為兩種

  • 靜態資源
  • 非靜態資源

什麼是靜態資源呢?你還記得 Vue Cli 專案底下有一個 public 資料夾嗎?那個資料夾就是專門放靜態資源的,而所謂的靜態資源就是不會被 Webpack 打包/編譯的資源,因此你可以直接在 HTML 中引入,例如:

1
<img src="/img/logo.png" alt="logo" />

而你的 logo.png 圖片位置就是在 public/img/logo.png。

那麼非靜態資源就是會透過 Webpack 打包/編譯的資源,因此你必須透過 import 的方式引入,例如:

1
import logo from './img/logo.png'

接著你就要這樣在 HTML 中引入:

1
<img :src="logo" alt="logo" />

編譯出來會跟靜態資源不一樣

1
<img src="/img/logo.1a2b3c.png" alt="logo" />

你會看到類似這樣的路徑,這就是 Webpack 打包/編譯後的路徑。

引入圖片的方式

前面有提到靜態資源的引入方式,其實相對就很簡單,只要放在 public 資料夾就可以直接引入

1
<img src="/img/logo.png" alt="logo" />

而 SCSS、CSS 也是一樣的道理,只要放在 public 資料夾就可以直接引入

SCSS:

1
2
3
.logo {
background-image: url('/img/logo.png');
}

CSS:

1
2
3
.logo {
background-image: url('/img/logo.png');
}

但是非靜態資源就稍微不一樣了,因為必須經過 Webpack 打包/編譯的關係,因此這類檔案大多都是放在 srcsrc/assets 資料夾底下。

那麼這邊必須先特別區分出兩種引入方式,尤其是 Vue Cli 與 Vite,因為這兩者的引入方式是有差異的。

Vue Cli

Vue Cli 本身是基於 Webpack 所製作的,因此引入圖片有以下幾種方式

  • import 引入
  • require 引入
  • 相對路徑引入
  • 別名引入

Vue Cli - import 引入

第一種引入方式相對簡單,只要透過 import 引入圖片,然後在 HTML 中使用 :src 來引入即可,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div class="home">
<img alt="Vue logo" :src="logo">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>

<script>
import logo from '@/assets/logo.png';
import HelloWorld from '@/components/HelloWorld.vue';

export default {
name: 'HomeView',
components: {
HelloWorld,
},
data() {
return {
logo,
};
},
};
</script>

你會發現必須將 logo 放置在 data 中,才能夠正確地引入圖片,因為這邊主要是使用 Options API,所以必須透過 data 來引入,而如果你使用 Composition API 的話,則可以直接透過 ref 來引入,例如:

1
2
import { ref } from 'vue';
import logo from '@/assets/logo.png';

所以兩者寫法上是有一點差異的

Vue Cli - require 引入

第二種是透過 require 引入

1
<img alt="Vue logo" :src="require('../assets/logo.png')">

這種方式相對簡單很多,直接寫在 HTML 中就可以了。

Vue Cli - 相對路徑引入

相對路徑的引入是比較特別的,那麼為什麼這一招可以呢?其實在 Vue Cli 官方中有提到他會將你以下程式碼

1
<img alt="Vue logo" src="../assets/logo.png">

轉換成

1
2
3
4
5
6
h('img', {
attrs: {
alt: 'Vue logo',
src: require('../assets/logo.png')
}
})

所以你也可以直接透過相對路徑來引入圖片,而這做法就跟第二種 require 引入是一樣的。

但這邊要注意一下,如果你的路徑是「絕對路徑」,例如:

1
<img alt="Vue logo" src="/assets/logo.png">

那麼 Vue Cli 在編譯時就不會特別做任何處理,所以輸出依然會是以下

1
<img alt="Vue logo" src="/assets/logo.png">

Vue Cli - 別名引入

別名引入分別區分了兩種,分別是 @~,但這兩種別名預設讀取的路徑是不同的

  • @ 預設讀取的路徑是 src 資料夾
  • ~ 預設讀取的路徑是 node_modules 資料夾

因此如果你要正確讀取到 assets 資料夾底下的圖片,那麼你必須這樣寫

1
<img alt="Vue logo" src="@/assets/logo.png">

當然也有另一種寫法,也就是 ~@

1
<img alt="Vue logo" src="~@/assets/logo.png">

這種 ~@ 寫法等價於 @

如果好奇 @ 的實現原理可以參考我先前寫的這一篇「vuejs中的小老鼠(at)符號代表什麼

Vite

接下來是關於 Vite 的部分,這邊要注意一下 Vite 的環境與 Vue Cli 不同,因此在引入圖片上可以用的方式也會有所不同。

  • import 引入
  • 相對路徑引入
  • 別名引入
  • require 引入

Vite - import 引入

第一種與 Vue Cli 相同,只要透過 import 引入圖片,然後在 HTML 中使用 :src 來引入即可,例如:

1
2
3
4
5
6
7
8
9
<script setup>
import logo from '@/assets/logo.svg'
</script>

<template>
<header>
<img alt="Vue logo" class="logo" :src="logo" width="125" height="125" />
</header>
</template>

Vite - 相對路徑引入

第二種是透過相對路徑引入,這種方式跟 Vue Cli 是一樣的,只要在 HTML 中使用相對路徑即可,例如:

1
2
3
4
5
<template>
<header>
<img alt="Vue logo" class="logo" src="../assets/logo.svg" width="125" height="125" />
</header>
</template>

Vite - 別名引入

Vite 本身也有提供別名引入

  • @ 預設讀取的路徑是 src 資料夾
  • ~ 預設讀取的路徑是 node_modules 資料夾

因此如果你要正確讀取到 assets 資料夾底下的圖片,那麼你必須這樣寫

1
2
3
4
5
<template>
<header>
<img alt="Vue logo" class="logo" src="@/assets/logo.svg" width="125" height="125" />
</header>
</template>

另一種一樣也可以寫 ~@

1
2
3
4
5
<template>
<header>
<img alt="Vue logo" class="logo" src="~@/assets/logo.svg" width="125" height="125" />
</header>
</template>

Vite - require 引入

只是這邊有一個地方要注意了,本身 Vite 並不支援 require 引入,這樣是會出現 require is not defined 的錯誤訊息的。

CSS 的部分

實戰開發上來講,我們時常會在 CSS 中引入圖片,不論是 Vue Cli 還是 Vite 基本上都是一樣的,主要是使用 url 來引入圖片,例如:

1
2
3
4
5
.logo {
width: 100px;
height: 100px;
background: url('./assets/logo.svg');
}

或是

1
2
3
4
5
.logo {
width: 100px;
height: 100px;
background: url('@/assets/logo.svg');
}

Liker 讚賞

這篇文章如果對你有幫助,你可以花 30 秒登入 LikeCoin 並點擊下方拍手按鈕(最多五下)免費支持與牡蠣鼓勵我。
或者你可以也可以請我「喝一杯咖啡(Donate)」。

Buy Me A Coffee Buy Me A Coffee

Google AD

撰寫一篇文章其實真的很花時間,如果你願意「關閉 Adblock (廣告阻擋器)」來支持我的話,我會非常感謝你 ヽ(・∀・)ノ