模拟反应元素上的点击事件

Posted

技术标签:

【中文标题】模拟反应元素上的点击事件【英文标题】: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 执行此操作。

【问题讨论】:

Trigger a button click from a non-button element的可能重复 @Tschallacka answer (***.com/a/6367609/5997711) 似乎可行,但不幸的是我没有得到任何结果。 【参考方案1】:

React 跟踪 mousedownmouseup 事件以检测鼠标点击,而不是像大多数其他事件一样跟踪 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 的出色答案稍作调整,模拟mousedownmouseupclick,就像在真正的鼠标点击期间发生的那样(否则 React 不会检测到它)。

这个答案在mousedownmouseup 事件之间添加了一个轻微的停顿以增加真实感,并将事件按正确的顺序排列(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);

  

【讨论】:

以上是关于模拟反应元素上的点击事件的主要内容,如果未能解决你的问题,请参考以下文章

单词上的点击事件反应原生

输入元素中的vuejs svg元素对点击事件没有反应

为啥 Firefox 对“选择”标签上的“点击”事件的反应与 Webkit 和 IE 不同?

a-table里添加不了点击事件

仅捕获不是由锚点点击引起的 hashchange 事件

javascript-事件