使用vanilla JavaScript

时间:2016-04-26 02:34:17

标签: javascript html reactjs

我有一个基于ReactJS的网站,我想以编程方式导航。基本上,工作流程是循环的:

  1. 点击Element1。
  2. 动态更改网页代码,在此期间添加Element2。
  3. 点击Element2。
  4. 等等,直到点击ElementN后,网页返回初始状态,并再次显示Element1。点击这些元素是我想从网站本身自动化的。

    我可以访问负责网站内容创建和更改的JS文件。我可以找到描述我感兴趣的元素的代码,并在需要时添加任何额外的事件监听器。

    我对客户端开发几乎全新,所以我解决此任务的方法纯粹是直观的。到目前为止,我的想法是为某些" onAdded"添加一个事件监听器。将元素添加到DOM时将触发的事件,并从该侦听器调用" onclick"监听器(或以其他方式发送"单击"事件)。但是,我无法找到任何表明DOM树添加的事件。

    因此,严格来说,我有两个问题:

    1. 上述方法是否可行(并且足够)?如果是这样,那么我究竟是如何完成它的呢?
    2. 如果我做错了,那么完成任务的正确方法是什么?
    3. 编辑1

      根据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文档,我将不胜感激。

1 个答案:

答案 0 :(得分:0)

好吧,我不确定是否应该回答一个像我一样亵渎的问题,但看起来我已经明白了。

我必须处理的缩小/混淆代码仍然具有React应用程序的突出功能,例如具有一系列回调的对象,如rendercomponentDidMountcomponentDidUpdate。所以,就像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应用程序进行粗暴相遇并且不知道从哪里开始的人。