Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 4x 7x 7x 7x 7x 7x 4x 4x 4x 4x 4x 4x 4x 4x 4x | import { toArray } from 'lodash-uni'
import { LiteralUnion } from '../types'
import { bindEvent } from './bindEvent'
import { wait } from './wait'
export interface ChooseFileOptions {
/**
* 是否多选
*
* @default false
*/
multiple?: boolean
/**
* 元素准备好后的回调
*/
afterElementReady?: (payload: { el: HTMLInputElement }) => any
}
/**
* 选择文件。
*
* @param accept 接受的文件类型,其中默认的 `image` 表示 `image/*`
* @param multiple 是否多选
* @returns 返回选中的文件列表
*/
export function chooseFile(
accept: LiteralUnion<'image', string>,
multiple?: boolean,
): Promise<ReadonlyArray<File>>
/**
* 选择文件。
*
* @param accept 接受的文件类型,其中默认的 `image` 表示 `image/*`
* @param options 选项
* @returns 返回选中的文件列表
*/
export function chooseFile(
accept: LiteralUnion<'image', string>,
options?: ChooseFileOptions,
): Promise<ReadonlyArray<File>>
export function chooseFile(
accept: LiteralUnion<'image', string>,
multipleOrOptions?: boolean | ChooseFileOptions,
): Promise<ReadonlyArray<File>> {
return new Promise(resolve => {
const options: ChooseFileOptions =
typeof multipleOrOptions === 'boolean'
? { multiple: multipleOrOptions }
: multipleOrOptions || {}
let input = document.createElement('input')
input.style.all = 'unset'
input.style.position = 'fixed'
input.style.top = '0px'
input.style.clip = 'rect(0, 0, 0, 0)'
input.style.webkitUserSelect = 'text'
// @ts-ignore
input.style.MozUserSelect = 'text'
// @ts-ignore
input.style.msUserSelect = 'text'
input.style.userSelect = 'text'
input.type = 'file'
input.accept = accept === 'image' ? 'image/*' : accept
input.multiple = !!options.multiple
options.afterElementReady?.({ el: input })
document.body.appendChild(input)
const handleChange = () => {
unbindChange()
unbindCancel()
unbindFocus()
unbindTouchend()
if (input) {
const files = input.files || []
document.body.removeChild(input)
input = null as any
resolve(Object.freeze(toArray(files)))
}
}
const unbindChange = bindEvent(input)('change', handleChange)
// 标准取消监听 但有兼容问题
// https://caniuse.com/?search=HTMLInputElement%20cancel
const unbindCancel = bindEvent(input)('cancel', handleChange)
// 取消监听 hack
// https://stackoverflow.com/a/67603015
const unbindFocus = bindEvent(window)('focus', () =>
wait(1000).then(handleChange),
)
const unbindTouchend = bindEvent(window)('touchend', () =>
wait(1000).then(handleChange),
)
input.click()
})
}
|