點燈坊

失くすものさえない今が強くなるチャンスよ

如何選擇目錄 ?

Sam Xiao's Avatar 2020-12-11

HTML 的 input(type='file') 預設只能選擇檔案,若要選擇目錄,則要使用 WebKit 特殊支援。

Version

Vue 3.0.11

Composition API

<template lang='pug'>
input(@input='onInput', ref='fileUpload', type='file', hidden, webkitdirectory)
button(@click='onUpload').border.border-gray-300.text-xs.text-gray-700.px-2.py-1 Upload
</template>

<script setup>
ref: fileUpload = null

let onUpload = () => fileUpload.click()

let onInput = () => {
  for (let x of fileUpload.files)
    console.log(x)
}
</script>

第 2 行

input(@input='onInput', ref='fileUpload', type='file', hidden, webkitdirectory)
button(@click='onUpload').border.border-gray-300.text-xs.text-gray-700.px-2.py-1 Upload

input(type='file') 特別加上 webkitdirectory attribute 才能選擇目錄。

第 9 行

let onUpload = () => fileUpload.click()

button 呼叫 fileUpload.click()

11 行

let onInput = () => {
  for (let x of fileUpload.files)
    console.log(x)
}

files 取得所選擇目錄的所有檔案。

Point-free

<template lang='pug'>
input(@input='onInput', ref='fileUpload', type='file', hidden, webkitdirectory)
button(@click='onUpload').border.border-gray-300.text-xs.text-gray-700.px-2.py-1 Upload
</template>

<script setup>
import { ref } from 'vue'
import { read } from 'vue3-fp'
import { pipe, prop, invoker } from 'ramda'
import { log } from 'wink-fp'

let fileUpload = ref (null)

let onUpload = pipe (
  read (fileUpload),
  invoker (0) ('click')
)

let onInput = pipe (
  read (fileUpload),
  prop ('files'),
  log
)
</script>

14 行

let onUpload = pipe (
  read (fileUpload),
  invoker (0) ('click')
)

使用 pipe() 組合 onUpload()

  • read (fileUpload):讀取 fileUpload ref
  • invoker (0) ('click'):呼叫 click()

19 行

let onInput = pipe (
  read (fileUpload),
  prop ('files'),
  log
)

使用 pipe() 組合 onInput()

  • read (fileUpload):讀取 fileUpload ref
  • prop ('files'):讀取 files prop
  • log:寫入 console.log()

Conclusion

  • webkitdirectory attribute 雖然非 W3C 標準,但目前主流 browser 都已經支援,可安心使用

Reference

MDN, HTMLInputElement.webkitdirectory