背景
我们在做web 端
文件上传的时候,可以明确的知道打开 文件选择器
,但是之前是不知道用户是否选择了文件,可能会通过一些 其他的检测手段达到我们目的。
取消选择
是一种用户行为,我们可能想要做一些额外的业务上的处理,比如弹出提示
, 数据埋点(埋用户取消行为的逻辑)
等等
const e = document.createElement('input')
e.type = 'file'
e.oncancel = () => {
}
// 或者
e.addEventListener('cancel', () => {
})
现在,我们可以通过 oncancel
或者 addEventListener
方式监听
这个行为跟 原生的 dialog 的取消是一样的,只是 浏览器支持的比较晚, dialog 原生对 cancel 事件支持非常好
(input cancel事件)
(Dialog cancel事件)
小结
- 用户点击 文件选择器弹窗的取消 会触发
- 键盘的ESC 也会触发
- 用户重新选择之前选择的相同文件时,文件输入也会触发它 (用户第一次选择A文件,再次打开,继续选择B文件,也会触发) 这种情况一般是非期望的,在 onchange 事件中,清除 input元素的
value
值就可以避免 - 另外: 按照下面 文档所说,不同浏览器对于 cancel 取消行为 可能会存在不一致,不同浏览器对于取消这个动作实现都可以有自己的标准。html.spec.whatwg.org/multipage/i…
番外
在阅读 @vue/use 源码 - 【useFileDialog】的时候,也发现对这个事件的支持
export function useFileDialog(options: UseFileDialogOptions = {}): UseFileDialogReturn {
const {
document = defaultDocument,
} = options
const files = ref<FileList | null>(null)
const { on: onChange, trigger: changeTrigger } = createEventHook()
const { on: onCancel, trigger: cancelTrigger } = createEventHook()
let input: HTMLInputElement | undefined
if (document) {
input = document.createElement('input')
input.type = 'file'
input.onchange = (event: Event) => {
const result = event.target as HTMLInputElement
files.value = result.files
changeTrigger(files.value)
}
// 这里 😊😊😊😊
input.oncancel = () => {
cancelTrigger()
}
}
const reset = () => {
files.value = null
if (input && input.value) {
input.value = ''
changeTrigger(null)
}
}
const open = (localOptions?: Partial<UseFileDialogOptions>) => {
if (!input)
return
const _options = {
...DEFAULT_OPTIONS,
...options,
...localOptions,
}
input.multiple = _options.multiple!
input.accept = _options.accept!
// webkitdirectory key is not stabled, maybe replaced in the future.
input.webkitdirectory = _options.directory!
if (hasOwn(_options, 'capture'))
input.capture = _options.capture!
if (_options.reset)
reset()
input.click()
}
return {
files: readonly(files),
open,
reset,
onCancel,
onChange,
}
}
参考链接
- can i use 地址
- MDN 地址, MDN截止到 2024-09-29 只有英文版本,和日文版本。
- html.spec.whatwg.org/multipage/i…