【问题标题】:Simulate click event on react element模拟反应元素上的点击事件
【发布时间】:2017-02-26 17:01:48
【问题描述】:

我正在尝试在 React 元素上模拟 .click() event,但我无法弄清楚它为什么不起作用(当我触发 event 时它没有反应)。

我想仅使用 JavaScript 发布 Facebook 评论,但我卡在第一步(在 div[class="UFIInputContainer"] 元素上执行 .click())。

我的代码是:

document.querySelector('div[class="UFIInputContainer"]').click();

这是我尝试执行此操作的 URL:https://www.facebook.com/plugins/feedback.php...

附:我对 React 没有经验,我真的不知道这在技术上是否可行。有可能吗?

编辑:我正在尝试从Chrome DevTools Console 执行此操作。

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

React 跟踪 mousedown 和 mouseup 事件以检测鼠标点击,而不是像大多数其他事件一样跟踪 click 事件。因此,不要直接调用click 方法或调度click 事件,而是必须调度down 和up 事件。为了更好地衡量,我还发送了 click 事件,但我认为这对 React 来说是不必要的:

const mouseClickEvents = ['mousedown', 'click', 'mouseup'];
function simulateMouseClick(element){
  mouseClickEvents.forEach(mouseEventType =>
    element.dispatchEvent(
      new MouseEvent(mouseEventType, {
          view: window,
          bubbles: true,
          cancelable: true,
          buttons: 1
      })
    )
  );
}

var element = document.querySelector('div[class="UFIInputContainer"]');
simulateMouseClick(element);

这个答案的灵感来自Selenium Webdriver code。

【讨论】:

  • 这很聪明,谢谢
  • 似乎不再起作用了,也许我们需要发送一个“更改”事件?
  • 这个解决方案在一段时间内运行良好,但最近失败了。你最终找到了替代的@information_interchange 吗?
  • 如果你们能提供开始破坏这个的 React 版本,那可以帮助我解决这个问题。
  • 大部分 React 应用都听“mousedown”事件而不是“click”,所以试试mouseClickEvents = ['mousedown']
【解决方案2】:

使用 react 16.8 我会这样做:

const Example = () => {
  const inputRef = React.useRef(null)
        
  return (
    <div ref={inputRef} onClick={()=> console.log('clicked')}>
      hello
    </div>
  )
}
    

然后简单地调用

inputRef.current.click()

【讨论】:

  • @tam,你的意思是 inputRef.current.handleClick() ??
  • @Gajen 是的。看来我打错了。
  • 这是正确和最好的解决方案。谢谢你..你拯救了我的一天:)
  • 这是 IMO 的最佳答案
  • 当我使用它时,单击一次后无法读取 null 的属性单击
【解决方案3】:

使用refs获取回调函数中的元素,使用click()函数触发点击。

class Example extends React.Component{
  simulateClick(e) {
    e.click()
  }
  render(){
    return <div className="UFIInputContainer"
    ref={this.simulateClick} onClick={()=> console.log('clicked')}>
      hello
      </div>
  }
}

ReactDOM.render(<Example/>, 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"></div>

【讨论】:

  • 感谢您的回答,但您将如何将其应用于此 URL:link?无法正常工作。
  • e.click is not a function
  • 应该是e.target.click()
  • 这对我不起作用,但是e.props 包含映射到元素上的任何函数。在我的例子中,它是一个带有onChange 的复选框,所以在simulateClick 中e.props.onChange() 工作得很好。
【解决方案4】:

如果您没有在组件中定义类,而是只声明:

function App() { ... }

在这种情况下,您只需要设置 useRef 钩子并使用它来指向/引用任何 html 元素,然后使用引用来触发常规 dom 事件。

import React, { useRef } from 'react';

function App() {
  const inputNameRef = useRef()
  const buttonNameRef = useRef()
  
  function handleKeyDown(event) {
    // This function runs when typing within the input text,
    // but will advance as desired only when Enter is pressed
    if (event.key === 'Enter') {
      // Here's exactly how you reference the button and trigger click() event,
      // using ref "buttonNameRef", even manipulate innerHTML attribute
      // (see the use of "current" property)
      buttonNameRef.current.click()
      buttonNameRef.current.innerHTML = ">>> I was forced to click!!"
    }
  }
  
  function handleButtonClick() {
    console.log('button click event triggered')
  }
  
  return (
    <div>
      <input ref={inputNameRef} type="text" onKeyDown={handleKeyDown}  autoFocus />
      <button ref={buttonNameRef} onClick={handleButtonClick}>
      Click me</button>
    </div>
  )
}

export default App;

【讨论】:

    【解决方案5】:

    从之前的解决方案中汲取灵感并使用一些 javascript 代码注入,也可以先 inject React 进入页面,然后在该页面元素上触发点击事件.

    let injc=(src,cbk) => { let script = document.createElement('script');script.src = src;document.getElementsByTagName('head')[0].appendChild(script);script.onload=()=>cbk() }
    injc("https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js",() => injc("https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js",() => {
    
    class ReactInjected extends React.Component{
      simulateClick(e) {
        e.click()
      }
      render(){
        return <div className="UFIInputContainer"
        ref={this.simulateClick} onClick={()=> console.log('click injection')}>
          hello
          </div>
      }
    }
    ReactDOM.render(<ReactInjected/>, document.getElementById('app'))
    
    } ))
    &lt;div id="app"&gt;&lt;/div&gt;

    【讨论】:

      【解决方案6】:

      对@carlin.scott 的出色答案稍作调整,模拟mousedown、mouseup 和click,就像在真正的鼠标点击期间发生的那样(否则 React 不会检测到它)。

      这个答案在mousedown 和mouseup 事件之间添加了一个轻微的停顿以增加真实感,并将事件按正确的顺序排列(click 最后触发)。暂停使其异步,这可能是不可取的(因此我不只是建议对@carlin.scott 的答案进行编辑)。

      async function simulateMouseClick(el) {
        let opts = {view: window, bubbles: true, cancelable: true, buttons: 1};
        el.dispatchEvent(new MouseEvent("mousedown", opts));
        await new Promise(r => setTimeout(r, 50));
        el.dispatchEvent(new MouseEvent("mouseup", opts));
        el.dispatchEvent(new MouseEvent("click", opts));
      }
      

      使用示例:

      let btn = document.querySelector("div[aria-label=start]");
      await simulateMouseClick(btn);
      console.log("The button has been clicked.");
      

      【讨论】:

        【解决方案7】:

        使用 React useRef Hooks,您可以像这样在任何按钮上触发点击事件:

        export default const () => {
        
            // Defining the ref constant variable
            const inputRef = React.useRef(null);
        
            // example use
            const keyboardEvent = () => {
              inputRef.current.handleClick(); //Trigger click
            }
        
            // registering the ref
            return (
               <div ref={inputRef} onClick={()=> console.log('clicked')}>
                  hello
               </div>
            )
        }
        

        【讨论】:

          【解决方案8】:

          有点肮脏的 hack,但这个对我来说效果很好,而这篇文章之前的建议都失败了。您必须在源代码中找到定义了onClick 的元素(为此,我必须在移动模式下运行网站)。该元素将有一个 __reactEventHandlerXXXXXXX 属性,允许您访问反应事件。

          let elem = document.querySelector('YOUR SELECTOR');
          //Grab mouseEvent by firing "click" which wouldn't work, but will give the event
          let event;
          likeBtn.onclick = e => {
            event = Object.assign({}, e);
            event.isTrusted = true; //This is key - React will terminate the event if !isTrusted
          };
          elem.click();
          setTimeout(() => {
            for (key in elem) {
              if (key.startsWith("__reactEventHandlers")) {
                elem[key].onClick(event);
              }
            }
          }, 1000);
          
            
          

          【讨论】:

            猜你喜欢
            • 2018-08-02
            • 2023-01-05
            • 1970-01-01
            • 1970-01-01
            • 2021-05-14
            • 1970-01-01
            • 2018-06-19
            • 1970-01-01
            • 2023-04-04
            相关资源
            最近更新 更多