若要上傳檔案,最簡單就是使用 HTML 的 <input type=file>
,但 HTML 的 <input>
顯示太過陽春,不太符合目前主流 Web 顯示,當然可以找 Package 達成需求,事實上以 Tailwind CSS 就能簡單實作出漂亮的 File Upload。
Version
Vue 3.0.5
Tailwind CSS 2.1.1
HTML
原生 HTML 的結果非常陽春。
<template>
<input type="file">
</template>
第 3 行
<input type="file">
只使用 HTML 的 <input type="file">
。
Tailwind CSS
改用 button 實現 file upload,可用千變萬化的 CSS 控制。
<template>
<input ref="fileUpload" type="file" accept="images/*" multiple hidden @input="onInput">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @click="onUpload()">
Upload
</button>
<p>{{ name }}</p>
</template>
<script setup>
ref: name = ''
ref: fileUpload = null
let onUpload = () => fileUpload.click()
let onInput = () => {
let files = fileUpload.files
for (let x of files)
name = x.name
}
</script>
第 2 行
<input ref="fileUpload" type="file" hidden>
一樣使用 HTML 的 <input type="file">
,但加上了 hidden
使其隱藏不顯示,另外加上了 ref="fileUpload"
供 Vue 使用。
第 3 行
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @click="onUpload()">Upload</button>
使用 HTML 的 <button>
搭配一堆 Tailwind CSS 的 utility 修飾:
- bg-blue-500:設定 button 背景為藍色
- hover-blue-700:設定當 button hover 時,背景會變為稍為深的藍色
- text-white:設定文字為白色
- font-bold:設定文字為粗體
- py-2:設定 Y 軸 padding
- px-4:設定 X 軸 padding,一般來說 button 會設定 X 軸 padding 較大
- rounded:設定 button 有圓角
當 click
時執行 onUpload()
。
第 6 行
<p> {{ name }} </p>
下方顯示檔案名稱。
11 行
ref: fileUpload = null
fileUpload
需使用 ref
設定成 null
。
13 行
let onUpload = () => fileUpload.click()
當 button click 時,執行 fileUpload.click()
。
15 行
let onInput = () => {
let files = fileUpload.files
for (let x of files)
name = x.name
}
當 fileUpload.click()
執行時是會執行 onInput()
。
使用 fileUpload.files
取得所有檔案,其為 Object Array,可由 name
取得 file name 。
Function Pipeline
改用 Function Pipeline 方式實現。
<template>
<input ref="fileUpload" type="file" accept="images/*" multiple hidden @input="onInput">
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" @click="onUpload">
Upload
</button>
<p>{{ name }}</p>
</template>
<script setup>
import { ref } from 'vue'
import { pipe, prop, forEach } from 'ramda'
import { read, write } from 'vue3-fp'
let name = ref('')
let fileUpload = ref(null)
let onUpload = pipe(
read(fileUpload),
x => x.click()
)
let showName = pipe(
prop('name'),
write(name)
)
let onInput = pipe(
read(fileUpload),
prop('files'),
forEach(showName),
)
</script>
14 行
let name = ref('')
let fileUpload = ref(null)
Function Pipeline 適合以 ref()
定義出始值。
17 行
let onUpload = pipe(
read(fileUpload),
x => x.click()
)
組合出當 button click 時的 onUpload()
:
read(fileUpload)
:讀出fileUpload
refx => x.click()
:執行fileUpload.click()
27 行
let onInput = pipe(
read(fileUpload),
prop('files'),
forEach(showName),
)
組合出 <input type="file">
的 onInput()
:
read(fileUpload)
:讀出fileUpload
refprop('files')
:讀出files
propforEach(showName)
:顯示所有檔案名稱
22 行
let showName = pipe(
prop('name'),
write(name)
)
顯示單一檔案名稱:
prop('name')
:讀出name
propwrite(name)
:寫入name
state
Conclusion
- File upload 其實不須另外找 package,只要 HTML 的
<input type="file">
與<button>
加上 Tailwind CSS 修飾即可