ReactJS - 如何检测何时在文件输入上单击“取消”?

问题描述 投票:0回答:3

当用户单击文件输入对话框上的十字图标取消按钮时,我想要一个事件或收到通知,以便我可以基于此执行一些任务。

仅当用户单击 Open 按钮时才会触发 onChange 事件。

当用户使用 ReactJS 单击十字图标取消按钮时,有没有办法收到通知?

下面是工作代码片段。

class Test extends React.Component {
  constructor() {
    super();
    this.fileInputClicked = this.fileInputClicked.bind(this);
  }
  
  fileInputClicked(event){
    let file = event.target.files[0];
    console.log("File is Selected", file);
  }

  render() {
    return (
      <div>
        <div>
          <p>Hello world</p>
            <input type="file" onChange={this.fileInputClicked}/>
        </div>
      </div>
    );
  }
}

ReactDOM.render(<Test/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app' />

javascript html reactjs file event-handling
3个回答
9
投票

嗯,这可能是我会做的,但我真的不喜欢它,而且我认为由于用户决定不上传文件而执行某些操作的整个想法并不是一个良好的用户体验,因此请明智地使用它。

fileInputClicked(event){
        let file = event.target.files[0];
        console.log("File is Selected", file);
        window.removeEventListener('focus', this.handleFocusBack);
}

handleFocusBack(){
    console.log('focus-back');
    window.removeEventListener('focus', this.handleFocusBack);
}

clickedFileInput(){
    window.addEventListener('focus', this.handleFocusBack);
}

render() {
    return (
        <div>
            <div>
                <p>Hello world</p>
                <input onClick={this.clickedFileInput} type="file" onChange={this.fileInputClicked}/>
            </div>
        </div>
    );
}

这样,当用户决定关闭文件输入时,他会重新关注窗口,您将获得所需的

handleFocusBack
功能,当他添加文件时,他会转到
fileInputClicked

Afaik,没有“开箱即用”的机制来实现你想要的。


0
投票

这是一个老问题,但我也需要一个答案。然而,解决方案比 @Matan-Bobi 建议的稍微复杂一些。

  • 单击浏览按钮时,
    在文件对话框打开之前
    会触发 click 事件。
  • 在这两种情况下,
    focus
    事件都会在文件对话框关闭后 被触发。也就是说,它是通过单击“文件对话框”中“打开”按钮上的“”或“取消”按钮上的“”来触发的。 单击“打开”按钮之后
  • 几毫秒会触发
  • change
     事件。如果单击“取消”按钮,则永远不会触发它。
    因此,要检测是否单击“取消”按钮,您必须再等待
  • 几毫秒
以确保没有触发

change事件。在我的测试中,100 毫秒似乎是一个不错的等待时间。

我下面的代码提供了太多信息(特别是如果您取消注释 
componentDidUpdate

方法中的行),但它允许您查看需要跳过的所有环节。

const CANCEL_DELAY = 100; let render = 0; class Test extends React.Component { constructor() { super(); this.state = { feedback: "Browse for a file...", filename: "", timeOut: 0 }; this.dialogOpened = this.dialogOpened.bind(this); this.dialogClosed = this.dialogClosed.bind(this); this.fileSelected = this.fileSelected.bind(this); this.cancelDialog = this.cancelDialog.bind(this); } dialogOpened() { console.log("Dialog opened"); window.addEventListener('focus', this.dialogClosed, { once: true}); this.setState(() => ({ filename: "" })); } dialogClosed() { console.log("Dialog closed"); console.time("closed_after"); const timeOut = setTimeout(this.cancelDialog, CANCEL_DELAY); console.log(`timeOut ${timeOut} created`); this.setState(() => ({ feedback: 'Dialog closed', timeOut })); } fileSelected() { console.timeEnd("closed_after"); // <25 ms on my computer const file = event.target.files[0]; this.setState(() => ({ feedback: `File was selected`, filename: file.name })); // TODO: Do something with the selected file console.log(`+++ File: ${file.name} selected +++`); this.destroyTimeout(); } cancelDialog() { console.log(`cancelDialog triggered after ${CANCEL_DELAY} ms`); console.timeEnd("closed_after"); this.setState(() => ({ feedback: "Dialog was cancelled" })); // TODO: Do something about the cancellation console.log("--- File dialog was cancelled ---"); this.destroyTimeout(); // > 103 ms } destroyTimeout() { console.log(`timeout ${this.state.timeOut} destroyed (${this.state.feedback}) `); clearTimeout(this.state.timeOut); this.setState(() => ({ timeOut: 0 })); } render() { return ( <div> <p>{this.state.feedback}</p> <input type="file" onClick={this.dialogOpened} onChange={this.fileSelected} /> <p>{this.state.filename}</p> </div> ); } componentDidUpdate() { // // Uncomment for more feedback // console.log(`Update ${++render}) updated state:`, this.state); } } ReactDOM.render(<Test/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> <div id='app' />

一个简单的方法是验证您的文件数组是否为空。

-1
投票
取消事件意味着用户尚未选择任何文件,这意味着:

事件.目标.文件.长度= 0

const onFileChange = (e) => { if(e.target.files.length ===0) { setFile(null); // undefined take place instead by default // the cancel event logics will always land here } else{ setResume(e.target.files[0]); } }


© www.soinside.com 2019 - 2024. All rights reserved.