內容目錄
Nuxt3 / Vue 3 動態取得圖片
參考資料
把圖片放在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。
就看專案目的取決要使用何種作法囉。