我有一个基于ReactJS的网站,我想以编程方式导航。基本上,工作流程是循环的:
等等,直到点击ElementN后,网页返回初始状态,并再次显示Element1。点击这些元素是我想从网站本身自动化的。
我可以访问负责网站内容创建和更改的JS文件。我可以找到描述我感兴趣的元素的代码,并在需要时添加任何额外的事件监听器。
我对客户端开发几乎全新,所以我解决此任务的方法纯粹是直观的。到目前为止,我的想法是为某些" onAdded"添加一个事件监听器。将元素添加到DOM时将触发的事件,并从该侦听器调用" onclick"监听器(或以其他方式发送"单击"事件)。但是,我无法找到任何表明DOM树添加的事件。
因此,严格来说,我有两个问题:
根据Matthew Herbst的建议,我研究了像componentDidMount
这样的React生命周期方法。事实证明,我想要自动点击的元素不是独立的React组件,而是在render
方法中添加了一些其他组件的内容,其中包含大量createElement
次调用。
所以现在问题从检测特定元素添加到DOM结构的时刻切换到找到与之交互的方式。
正如我目前所看到的那样,简单(和丑陋)的方法是使用window
中的componentDidMount
对象,找到我要点击data-reactid
的元素属性(这是一个点分隔数字的字符串,从我所知,它是动态生成并反映元素层次结构)然后调度所需的DOM事件。
它可能有效,但如果文档结构发生变化,则data-reactid
的值会再次被破坏。我宁愿以某种方式正确派遣React自己的onClick
事件,但我不知道如何。我尝试将传递给createElement
方法的函数作为onClick
componentDidMount
属性的值调用,但由于某种原因它无法正常工作。
我也尝试过与this article中描述的DOM交互方法,但在我看来,ReactDOM
对象似乎没有被定义。
由于我不是一个客户端开发人员,特别是不是React大师,我不能真正看到网站的客户端逻辑是如何工作的全貌,以及与我合作的代码似乎被缩小/混淆以使其更难。因此,如果有人提供任何具体建议而不让我阅读所有React文档,我将不胜感激。
答案 0 :(得分:0)
好吧,我不确定是否应该回答一个像我一样亵渎的问题,但看起来我已经明白了。
我必须处理的缩小/混淆代码仍然具有React应用程序的突出功能,例如具有一系列回调的对象,如render
,componentDidMount
或componentDidUpdate
。所以,就像Matthew Herbst建议的那样,我调查了他们所做的事情。
点击我需要自动化的元素是在render
方法中通过长createElement
次调用创建的,看起来像这样:
T["default"].createElement("li", null, T["default"].createElement("div", {
className: P["default"].img
}, T["default"].createElement("img", {
src: n(600),
alt: ""
}), T["default"].createElement("b", null , "+3")), T["default"].createElement("h4", null , "«Header text»", T["default"].createElement("b", null , "+3")), T["default"].createElement("p", null , "Description"), T["default"].createElement("div", {
className: P["default"].btn
}, T["default"].createElement(A.Btn, {
mod: "info",
onClick: this._router.bind(this, "/gtr", "gtr")
}, "Play")))
我应该在原帖中发布该代码,但当时我并不真正理解这里发生了什么。
事实证明,T["default"]
引用的对象是React
对象,这意味着T["default"].createElement
次调用实际上等同于React.createElement
次。
然后,article by James K. Nelson帮助了解,为了找到组件的特定子项,我需要为其分配ref
属性。我需要访问“播放”按钮,所以我尝试将ref
属性添加到看起来像它的描述符对象,所以它看起来像
T["default"].createElement(A.Btn, {
mod: "info",
ref: "automatedElement1",
onClick: this._router.bind(this, "/gtr", "gtr")
}, "Play")
,它有效。现在,在componentDidUpdate
方法中,我可以使用像
if (this.refs.hasOwnProperty("automatedElement1")) {
var buttonElement = this.refs.automatedElement1;
}
不幸的是,我不太明白如何从这个对象到它的DOM反射,但通过简单地研究它的内容,我设法找到一个对应于HTML的data-reactid
属性值的属性该按钮的元素。所以我发现没有比使用document.querySelector
方法获取元素的DOM节点更聪明的解决方案:
var buttonNode = document.querySelector('button[data-reactid="' + buttonElement._reactInternalInstance._rootNodeID + '"]');
if (buttonNode) {
buttonNode.click();
}
这可能是一个糟糕的解决方案,但这是我在我的情况下设法找到的解决方案,并且它有效。希望它可以帮助那些与React应用程序进行粗暴相遇并且不知道从哪里开始的人。