Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

Nuxt3 / Vue 3 動態取得圖片

內容目錄

Nuxt3 / Vue 3 動態取得圖片

參考資料

https://www.lichter.io/articles/nuxt3-vue3-dynamic-images/https://clairechang.tw/2023/09/12/nuxt3/nuxt-v3-assets-vs-public/

把圖片放在assets中後,通常來說會使用這兩種寫法

<img src="@/assets/image/logo.jpg"> 
<img src="../assets/image/logo.jpg">

但只限於靜態圖片,如果想要動態取用圖片。
例如有10張圖片,檔名是1~10,例如001.jpg ~ 010.jpg

以前我偷懶會這樣處理:
放在 public 中,直接取用

<img src="`/image/${index}.jpg`">

但這種作法有些缺點,

  • 圖片將被瀏覽器快取住,因此如果我們想要更改圖像,我們也必須更改檔案名稱。這不是最佳的,特別是如果我們想在多個地方使用相同的圖像。
  • 效能問題,圖片不會被Vite插件之類最佳化。
  • 圖片將以原始大小加載,如果尺寸很大,同樣也有瀏覽器效能問題。
  • 管理不一致,這是我的使用習慣,我不喜歡圖片要放在public裡面,比較偏好在assets中一起管理。

如果換成assets中的話….

<img src="../assets/image/${index}.jpg`">

會失效。代表取用不到資源

如果找解決方式可能會找到 Vue2 時代的作法,加入 require,例如

<img :src="require(`.../assets/image/${index}.jpg`)" :alt="selectedDog">

但這個作法在Vue3 / Nuxt3 不能用了,因為Vite不支援。

這時要使用另一個Vite的API,import.meta.glob

我的理解,import.meta.glob有點像是先整理所有引入資料夾中的檔案,建立成一個索引,然後透過key去對應檔名。

<script setup lang="ts">

const glob = import.meta.glob('@/assets/images/*.jpg', { eager: true })
</script>

去檢查 glob 可以看到以下類似資料

{
  "/assets/images/logo_1`.jpg": {
    "default": "/_nuxt/assets/images/logo_1.jpg"
  },
  "/assets/images/logo_2.jpg": {
    "default": "/_nuxt/assets/images/logo_2.jpg"
  },
  "/assets/images/logo_3.jpg": {
    "default": "/_nuxt/assets/images/logo_3.jpg"
  }
}

這時我們用呼叫的圖檔名去尋找真實位置

<img :src="glob[`/assets/images/${index}.jpg`]" alt="" />

當然也有一些缺點

  • 圖片名稱會因為Vite快取關係被更改。
  • 同樣也可能有效能消耗,因為先處理了glob的API。

就看專案目的取決要使用何種作法囉。