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 | .logo { |
CSS:
1 | .logo { |
但是非靜態資源就稍微不一樣了,因為必須經過 Webpack 打包/編譯的關係,因此這類檔案大多都是放在 src
或 src/assets
資料夾底下。
那麼這邊必須先特別區分出兩種引入方式,尤其是 Vue Cli 與 Vite,因為這兩者的引入方式是有差異的。
Vue Cli
Vue Cli 本身是基於 Webpack 所製作的,因此引入圖片有以下幾種方式
import
引入require
引入- 相對路徑引入
- 別名引入
Vue Cli - import 引入
第一種引入方式相對簡單,只要透過 import
引入圖片,然後在 HTML 中使用 :src
來引入即可,例如:
1 | <template> |
你會發現必須將 logo
放置在 data
中,才能夠正確地引入圖片,因為這邊主要是使用 Options API,所以必須透過 data
來引入,而如果你使用 Composition API 的話,則可以直接透過 ref
來引入,例如:
1 | import { ref } from 'vue'; |
所以兩者寫法上是有一點差異的
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 | h('img', { |
所以你也可以直接透過相對路徑來引入圖片,而這做法就跟第二種 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 | <script setup> |
Vite - 相對路徑引入
第二種是透過相對路徑引入,這種方式跟 Vue Cli 是一樣的,只要在 HTML 中使用相對路徑即可,例如:
1 | <template> |
Vite - 別名引入
Vite 本身也有提供別名引入
@
預設讀取的路徑是src
資料夾~
預設讀取的路徑是node_modules
資料夾
因此如果你要正確讀取到 assets
資料夾底下的圖片,那麼你必須這樣寫
1 | <template> |
另一種一樣也可以寫 ~@
1 | <template> |
Vite - require 引入
只是這邊有一個地方要注意了,本身 Vite 並不支援 require
引入,這樣是會出現 require is not defined
的錯誤訊息的。
CSS 的部分
實戰開發上來講,我們時常會在 CSS 中引入圖片,不論是 Vue Cli 還是 Vite 基本上都是一樣的,主要是使用 url
來引入圖片,例如:
1 | .logo { |
或是
1 | .logo { |