如何在ReactJS中手动触发点击事件?

161
我如何在ReactJS中手动触发点击事件? 当用户单击element1时,我希望自动触发对标记的单击。
结果为:

如何在ReactJS中手动触发点击事件?当用户单击element1时,我希望自动触发对input标记的单击。

<div className="div-margins logoContainer">
  <div id="element1" className="content" onClick={this.uploadLogoIcon}>
    <div className="logoBlank" />
  </div>
  <input accept="image/*" type="file" className="hide"/>
</div>

看一些外部库,似乎以编程方式创建输入元素是一个好主意:https://github.com/okonet/react-dropzone/blob/master/src/index.js#L7 - Ahmed Nuaman
我不明白为什么你会想在React中这样做。你想要做什么? - tobiasandersen
@tobiasandersen,以编程方式聚焦“input”元素是完全有效的用例,这很可能是提问者想要通过编程触发的点击来实现的目标。 - John Weisz
当然可以,focus和blur都是完全有效的。但是点击呢?我问这个问题的原因是,如果例如聚焦是使用案例,那么最好展示它。但是如果点击确实是使用案例,那么最好只调用处理程序。 - tobiasandersen
@JohnWhite 好吧,它可能被正确地绑定了 :) 但你可能是对的,而且我的意思并不是要表现得刻薄。只是想看看这背后的真正意图是什么。 - tobiasandersen
14个回答

164
您可以使用 ref 属性通过回调获得对底层的 HTMLInputElement 对象的引用,并将其存储为类属性,然后使用该引用在事件处理程序中稍后触发点击,使用 HTMLElement.click 方法。

在您的 render 方法中:

<input ref={input => this.inputElement = input} ... />

在你的事件处理程序中:

this.inputElement.click();

完整示例:

class MyComponent extends React.Component {
  render() {
    return (
      <div onClick={this.handleClick}>
        <input ref={input => this.inputElement = input} />
      </div>
    );
  }

  handleClick = (e) => {
    this.inputElement.click();
  }
}

请注意使用ES6箭头函数来提供回调中正确的词法作用域。还要注意,通过这种方式获取的对象类似于使用document.getElementById获取到的对象,即实际的DOM节点。


7
这对我没有效果。不确定是否过时,但我成功地分配了该元素,但在调用“click”时,“click”未定义。我可以看到我分配给该元素的所有其他属性和回调函数。有什么想法吗? - TheJKFever
62
“Refs不再返回文档DOM节点,它们返回对React虚拟DOM节点的引用。”这是一个误解。参考文献并不返回“虚拟DOM”节点。资料来源:我从事React开发工作。 - Dan Abramov
5
那么,这方面有什么建议的方法吗? - alegria
1
@JohnWeisz 非常感谢,这对我很有帮助。我必须处理表单外的点击,因为我需要在按钮和表单之间放置一些元素。 - Markus Ethur
3
如果您在使用TypeScript,那么可能由于输入的类型为HTMLInputElement | null,而导致click未定义,因此请使用以下代码来编译:onClick={() => { if(inputElement) (inputElement).click(); } }。请注意不要改变原意。 - Jamie Twells
显示剩余7条评论

44

这是Hooks解决方案:

import React, {useRef} from 'react';

const MyComponent = () => {
    const myRefname= useRef<HTMLInputElement>(null);
    const handleClick = () => {
        myRefname.current.focus();
     }

    return (
        <div onClick={handleClick}>
            <input ref={myRefname}/>
        </div>
    );
}

11
"myRefname.current.focus is not a function" 翻译为:我的 Refname 当前没有 focus 函数。 - Spoderman4
1
你救了我的命。 - pnbps
1
@Spoderman4 只需为useRef函数指定一个类型。例如:const myRef = useRef<HTMLInputElement>(null); - Juan Herrera
2
好的答案,使用myRefname.current.click(); - Chris

32

使用ES6在2018年5月让以下内容工作了

参考React文档:https://reactjs.org/docs/refs-and-the-dom.html

import React, { Component } from "react";
class AddImage extends Component {
  constructor(props) {
    super(props);
    this.fileUpload = React.createRef();
    this.showFileUpload = this.showFileUpload.bind(this);
  }
  showFileUpload() {
    this.fileUpload.current.click();
  }
  render() {
    return (
      <div className="AddImage">
        <input
          type="file"
          id="my_file"
          style={{ display: "none" }}
          ref={this.fileUpload}
        />
        <input
          type="image"
          src="http://www.graphicssimplified.com/wp-content/uploads/2015/04/upload-cloud.png"
          width="30px"
          onClick={this.showFileUpload}
        />
      </div>
    );
  }
}
export default AddImage;

这似乎更加偏向于 React 导向 的答案。 - Ritik
在ReactJS中,使用innerRef={this.fileUpload}而不是ref={this.fileUpload}。其余代码正常工作。 - Chandan Chhajer

10
你可以使用 ref 回调函数,它会返回相应的 node。在此节点上调用 click() 函数即可进行程序化点击。
获取 div 节点。
clickDiv(el) {
  el.click()
}

ref设置为div节点

<div 
  id="element1"
  className="content"
  ref={this.clickDiv}
  onClick={this.uploadLogoIcon}
>

请查看这个jsfiddle链接:

https://jsfiddle.net/pranesh_ravi/5skk51ap/1/

希望对您有所帮助!


当您链接到JSFiddle时,将相关代码至少放在此处被视为良好的实践(顺便说一句:片段编辑器也支持ReactJS)。 - Icepickle
4
值得注意的是,尽管字符串ref方法并没有被废弃,但它被认为是过时的功能,已被基于回调函数的语法所取代:ref={elem => this.elem = elem} -- 这在Refs to Components中有详细说明。 - John Weisz
1
@JohnWhite 有价值的建议。已更新答案! - Pranesh Ravi
1
此外,在执行该操作之前,您需要检查并确保 el 不为 null/undefined。 - janex

9
在功能组件中,这个原则同样适用,只是语法和思考方式略有不同。
const UploadsWindow = () => {
  // will hold a reference for our real input file
  let inputFile = '';

  // function to trigger our input file click
  const uploadClick = e => {
    e.preventDefault();
    inputFile.click();
    return false;
  };

  return (
    <>
      <input
        type="file"
        name="fileUpload"
        ref={input => {
          // assigns a reference so we can trigger it later
          inputFile = input;
        }}
        multiple
      />

      <a href="#" className="btn" onClick={uploadClick}>
        Add or Drag Attachments Here
      </a>
    </>
  )

}

8
this.buttonRef.current.click();

2
这解决了我的问题,我不知道为什么有人取消投票这个代码。 - Francesco Orsi
是的,它需要关于useRef的更多上下文,这样我们可以在其他答案中找到,但这绝对是今天/2023年的答案。 - Chris

6

参考 Aaron Hakala 的答案,使用 useRef。灵感来源于这个答案:https://dev59.com/OFkS5IYBdhLWcg3wSk1G#54316368

const myRef = useRef(null);

  const clickElement = (ref) => {
    ref.current.dispatchEvent(
      new MouseEvent('click', {
        view: window,
        bubbles: true,
        cancelable: true,
        buttons: 1,
      }),
    );
  };

你的JSX代码:

<button onClick={() => clickElement(myRef)}>Click<button/>
<input ref={myRef}>

5
使用React Hooks和useRef hook
import React, { useRef } from 'react';

const MyComponent = () => {
    const myInput = useRef(null);

    const clickElement = () => {
        // To simulate a user focusing an input you should use the
        // built in .focus() method.
        myInput.current?.focus();

        // To simulate a click on a button you can use the .click()
        // method.
        // myInput.current?.click();
    }

    return (
        <div>
            <button onClick={clickElement}>
                Trigger click inside input
            </button>
            <input ref={myInput} />
        </div>
    );
}

对我来说,点击和聚焦不可用,这个方法并没有起作用。但是这个答案有效:https://dev59.com/OFkS5IYBdhLWcg3wSk1G#54316368如果你尝试使用以下代码:myInput.current?.click(); 而改为:myInput.current.dispatchEvent( new MouseEvent('click', { view: window, bubbles: true, cancelable: true, buttons: 1, }), );它应该可以工作。 - Jack Bridger
什么是 myInput.current?.focus(); 中的问号意思? - Julio de Leon
@JuliodeLeon 这是 JavaScript 最近引入的“可选链”。 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Optional_chaining当您想要访问或调用可能未定义的对象上的函数时,可以使用它。 - Jack Bridger

2

请尝试以下方法,如果不起作用,请告诉我:

<input type="checkbox" name='agree' ref={input => this.inputElement = input}/>
<div onClick={() => this.inputElement.click()}>Click</div>

点击 div 应该模拟点击 input 元素


1

对于TypeScript,您可以使用以下代码来避免出现类型错误:

import React, { useRef } from 'react';

const MyComponent = () => {
    const fileRef = useRef<HTMLInputElement>(null);

    const handleClick = () => {
      fileRef.current?.focus();
    }

    return (
        <div>
            <button onClick={handleClick}>
                Trigger click inside input
            </button>
            <input ref={fileRef} />
        </div>
    );
}


1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接