无法通过将文件拖放到按钮外的区域来选择文件,但仅在使用 Shadow 时才在 input 内选择文件 DOM

Cannot choose file by dropping file on area outside the button but inside input only when using Shadow DOM

在chrome中,可以将以下输入元素拖放到输入的底部区域。 我期待这种行为。

<input type="file" class="input-file">

<style>
.input-file {
    display: block;
    width: 300px;
    height: 300px;
    border: 1px solid red;
    margin: 10px;
}
</style>

但是Shadow内部就不一样了DOM。 可以将以下输入元素拖放到仅位于输入左上方区域的 "choose file" 按钮。 当文件被拖放到输入的底部区域时,拖放的文件未被选择。

customElements.define("foo-bar", class extends HTMLElement {
    constructor(){
        super()
        this.attachShadow({mode: "open"}).innerHTML = `
            <input type="file" class="input-file">

            <style>
            .input-file {
                display: block;
                width: 300px;
                height: 300px;
                border: 1px solid red;
                margin: 10px;
            }
            </style>
        `
    }
})
document.body.innerHTML = "<foo-bar></foo-bar>"

我认为这是由于 Shadow 之外的事件未被通知而导致的错误 DOM。

有解决办法吗?

解决方法是处理 drop 事件。

this.shadowRoot.querySelector( 'input' ).ondrop = ev => {
    console.log( 'dropped in', ev.dataTransfer.items.length  )
    for ( var i = 0 ; i < ev.dataTransfer.items.length ; i++ ) {
        if (ev.dataTransfer.items[i].kind === 'file') {
            var file = ev.dataTransfer.items[i].getAsFile()
            console.log( 'file[' + i + '].name = ' + file.name )
        }
    }
    ev.preventDefault()
}

不要忘记调用 preventDefault() 方法来中止文件打开。