模拟反应元素上的点击事件
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 跟踪 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'))
))
<div id="app"></div>
【讨论】:
【参考方案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);
【讨论】:
以上是关于模拟反应元素上的点击事件的主要内容,如果未能解决你的问题,请参考以下文章