Javascript 如何通过另一个DOM触发输入文件事件

Javascript 如何通过另一个DOM触发输入文件事件,javascript,reactjs,Javascript,Reactjs,我有一个输入按钮和输入文件,我想点击按钮,它会在REACT JS中触发输入文件事件 然后按下按钮 React.createElement('a',{onClick: this.doClick},'Select File') 那么,当我们单击A HREF时,如何定义和触发输入文件单击事件呢 谢谢你的帮助。 :-编辑:这是我很久以前回答的一个问题,我不知道现在有多少反应。有趣的是,它被认为是有效的 因此,对于阅读此答案的任何人;这个答案是错误的,这是一个很好的例子,说明了你不应该在react中做的

我有一个输入按钮和输入文件,我想点击按钮,它会在REACT JS中触发输入文件事件

然后按下按钮

React.createElement('a',{onClick: this.doClick},'Select File')
那么,当我们单击A HREF时,如何定义和触发输入文件单击事件呢

谢谢你的帮助。 :-

编辑:这是我很久以前回答的一个问题,我不知道现在有多少反应。有趣的是,它被认为是有效的

因此,对于阅读此答案的任何人;这个答案是错误的,这是一个很好的例子,说明了你不应该在react中做的事情

请在下面找到一个很好的反模式,同样,不要这样做

=================================================

您可以使用jQuery实现这一点:

this.doClick: function() {
    $('input[type=file]').trigger('click');
}

React不提供触发事件的特定函数,您可以使用jQuery或简单地使用本机Javascript:请参阅MDN上的事件。您不需要jQuery来实现此目的。您甚至不需要事件处理程序。HTML对此有一个特定的元素,称为

首先,确保输入元素具有id属性:

React.createElement('input',{type:'file', name:'myfile', id:'myfile'})
然后,而不是:

React.createElement('a',{onClick: this.doClick},'Select File')
尝试:

另一种解决方案是将输入元素作为标签的子元素,而不是添加htmlFor和id属性


现在单击标签应该触发与单击输入本身相同的行为。

您可以使用ref,f.e:

在类组件上:

<input 
    ref={fileInput => this.fileInput = fileInput} 
    type="file"
 />
<button onClick={this.triggerInputFile}> Select File </button>
在功能组件中使用useRef钩子。需要^16.8

const Dummy = () => {
  const inputFileRef = useRef( null );

  const onFilechange = ( e ) => {
    /*Selected files data can be collected here.*/
    console.log( e.target.files );
  }
  const onBtnClick = () => {
    /*Collecting node-element and performing click*/
    inputFileRef.current.click();
  }

  return (
    <form className="some-container">
      <input
        type="file"
        ref={inputFileRef}
        onChange={onFileChange}
      />
      <button onClick={onBtnClick}>Select file</button>
    </form>
  )
}
使用React.createRef类实现,并使用节点元素处理单击

使用挂钩:


基于@YÒGÎ的答案,下面是一个使用TypeScript的实现:

class Dummy extends React.Component {
    fileInputRef: React.RefObject<HTMLInputElement> = React.createRef();

    forwardClickToInputElement = () => {
        this.fileInputRef.current!.click();
    };

    handleUploadDemand = (ie: ChangeEvent<HTMLInputElement>) => {
        const fileList: FileList = ie.target.files;

        // do something with the FileList, for example:
        const fileReader = new FileReader();
        fileReader.onload = () => {
            const str = String(fileReader.result);
            try {
                const parsedContent = YOUR_OWN_PARSING(str);
            } catch (error) {
                // YOUR OWN ERROR HANDLING
            }
        };
        fileReader.readAsBinaryString(fileList[0])
    }

    render() {
        return (
            <div className="some-container">
                <button onClick={this.forwardClickToInputElement}>Select File</button>
                <input ref={this.fileInputRef} type="file" onChange={this.handleSelectFile} hidden={true}/>
            </div>
        )
    }
}
参考资料:

如何在React with Typescript中使用引用的解决方案 使用ref类型窄化运算符
React.createElement'input',{type:'file',name:'myfile'}然后点击React.createElement'a',{onClick:this.doClick},'Select file',那么当我们点击a HREF时如何定义和触发输入文件点击事件呢?是的,目前我总是这样做,但我需要的是找到通过React触发的方法,不是jQuery使用React的原因是为了避开jQuery。这个答案很糟糕。jQuery完全提供了对DOM的控制,而react则相反。强烈建议不要将它们一起使用。谢谢好心的先生!这是正确的方法,应该是一个公认的答案。那么如何将上传的文件保存在状态变量中呢?我在输入中添加了一个onChange,但它不起作用??在输入标记中使用onChange属性处理它。e、 target.files[0]}/>如何确保已填充ref?它不会触发渲染,因此在函数组件中,ref的第一个渲染始终为null。每次重新渲染只是为了抓取ref实例是否被认为是最佳实践?null只是为了标识为引用初始值。安装组件后,将为参考对象指定其当前元素。在我们的用例中,可以在componentDidMount之后执行输入操作。因此,无论是否使用任何初始值,都是安全的。来自userefsource:请记住,useRef的内容更改时不会通知您。更改.current属性不会导致重新渲染。
triggerInputFile = () => this.fileInput.click()
const Dummy = () => {
  const inputFileRef = useRef( null );

  const onFilechange = ( e ) => {
    /*Selected files data can be collected here.*/
    console.log( e.target.files );
  }
  const onBtnClick = () => {
    /*Collecting node-element and performing click*/
    inputFileRef.current.click();
  }

  return (
    <form className="some-container">
      <input
        type="file"
        ref={inputFileRef}
        onChange={onFileChange}
      />
      <button onClick={onBtnClick}>Select file</button>
    </form>
  )
}
class Dummy extends React.Component {
    
  constructor( props ) {
    super( props );

    this.inputFileRef = React.createRef();
    this.onFileChange = this.handleFileChange.bind( this );
    this.onBtnClick = this.handleBtnClick.bind( this );
  }

  handleFileChange( e ) {
    /*Selected files data can be collected here.*/
    console.log( e.target.files );
  }

  handleBtnClick() {
    /*Collecting node-element and performing click*/
    this.inputFileRef.current.click();
  }

  render() {
    return (
      <form className="some-container">
        <input
          type="file"
          ref={this.inputFileRef}
          onChange={this.onFileChange}
        />
        <button onClick={this.onBtnClick}>Select file</button>
      </form>
    )
  }
}
import React, {useRef} from 'react';
const FancyInput = () => {
    const fileInput = useRef(null)

    const handleClick = () => {
        fileInput.current.click()
    }

    const handleFileChange = event => {
        console.log("Make something")
    }

    return(
        <div className="patientactions-container">
            <input
                type="file"
                onChange={(e) => handleFileChange(e)}
                ref={fileInput} 
            />
            <div onClick={() => handleClick()}></div>
        </div>
    )
}
export default FancyInput;
class Dummy extends React.Component {
    fileInputRef: React.RefObject<HTMLInputElement> = React.createRef();

    forwardClickToInputElement = () => {
        this.fileInputRef.current!.click();
    };

    handleUploadDemand = (ie: ChangeEvent<HTMLInputElement>) => {
        const fileList: FileList = ie.target.files;

        // do something with the FileList, for example:
        const fileReader = new FileReader();
        fileReader.onload = () => {
            const str = String(fileReader.result);
            try {
                const parsedContent = YOUR_OWN_PARSING(str);
            } catch (error) {
                // YOUR OWN ERROR HANDLING
            }
        };
        fileReader.readAsBinaryString(fileList[0])
    }

    render() {
        return (
            <div className="some-container">
                <button onClick={this.forwardClickToInputElement}>Select File</button>
                <input ref={this.fileInputRef} type="file" onChange={this.handleSelectFile} hidden={true}/>
            </div>
        )
    }
}