在反应元素上模拟点击事件
Simulate click event on react element
我正在尝试在 React 元素上模拟 .click()
event
但我无法弄清楚为什么它不起作用(当我发射 event
).
我想 post 仅使用 JavaScript 的 Facebook 评论,但我卡在了第一步(在 div[class="UFIInputContainer"]
元素上执行 .click()
)。
我的代码是:
document.querySelector('div[class="UFIInputContainer"]').click();
这里是 URL 我正在尝试这样做的地方:https://www.facebook.com/plugins/feedback.php...
P.S。我对 React 没有经验,我真的不知道这在技术上是否可行。可能吗?
编辑:我正在尝试从 Chrome DevTools Console
执行此操作。
使用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>
从以前的解决方案中得到启发,并使用一些 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>
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。
对于 React 16.8,我会这样做:
const Example = () => {
const inputRef = React.useRef(null)
return (
<div ref={inputRef} onClick={()=> console.log('clicked')}>
hello
</div>
)
}
只需调用
inputRef.current.click()
使用 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>
)
}
对@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.");
如果您没有在组件中定义 class,而是只声明:
function App() { ... }
在这种情况下,您只需要设置 useRef 挂钩并将其用于 point/refer 任何 html 元素,然后将引用用于定期触发 dom-events.
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;
有点肮脏的黑客攻击,但这个对我来说效果很好,而这个 post 之前的建议都失败了。您必须找到在源代码中定义了 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);
我正在尝试在 React 元素上模拟 .click()
event
但我无法弄清楚为什么它不起作用(当我发射 event
).
我想 post 仅使用 JavaScript 的 Facebook 评论,但我卡在了第一步(在 div[class="UFIInputContainer"]
元素上执行 .click()
)。
我的代码是:
document.querySelector('div[class="UFIInputContainer"]').click();
这里是 URL 我正在尝试这样做的地方:https://www.facebook.com/plugins/feedback.php...
P.S。我对 React 没有经验,我真的不知道这在技术上是否可行。可能吗?
编辑:我正在尝试从 Chrome DevTools Console
执行此操作。
使用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>
从以前的解决方案中得到启发,并使用一些 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>
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。
对于 React 16.8,我会这样做:
const Example = () => {
const inputRef = React.useRef(null)
return (
<div ref={inputRef} onClick={()=> console.log('clicked')}>
hello
</div>
)
}
只需调用
inputRef.current.click()
使用 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>
)
}
对@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.");
如果您没有在组件中定义 class,而是只声明:
function App() { ... }
在这种情况下,您只需要设置 useRef 挂钩并将其用于 point/refer 任何 html 元素,然后将引用用于定期触发 dom-events.
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;
有点肮脏的黑客攻击,但这个对我来说效果很好,而这个 post 之前的建议都失败了。您必须找到在源代码中定义了 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);