Puppeteer如何处理单击对象/DevTools协议Chromium/Chrome [英] How does Puppeteer handle the click Object / DevTools Protocol Chromium/Chrome

查看:47
本文介绍了Puppeteer如何处理单击对象/DevTools协议Chromium/Chrome的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要知道操纵up的人如何处理click对象以及Chromium DevTools API.我试图自己研究它,但发现自己无法找到处理它的实际代码.

I need to know how puppeteer handles the click object, as well as Chromium DevTools API. I've tried to research it on my own and have found myself not being able to find the actual code that handles it.

我需要知道的原因是我正在开发一个包装器,该包装器在用于测试Web页面的代码中测试事件,并希望查看实现事件处理例程是否有益,而不是使用事件的伪造接口(单击和点击悬停,以及其他可能需要的事件,例如触摸事件或滚动)

The reason why I need to know is I'm developing a wrapper that tests events in code for testing Web Pages, and was looking to see if implementing a event handling routine is beneficial instead of using puppeteers interface of events (clicks and taps an hover, as well as other events that might be needed like touch events, or scrolling)

这是我走了多远:

Puppeteer API使用DevTools的框架逻辑来联系API: https://github.com/puppeteer/puppeteer/blob/master/lib/Page.js

Puppeteer API uses the Frame Logic of DevTools to contact API: https://github.com/puppeteer/puppeteer/blob/master/lib/Page.js

    /**
       * @param {string} selector
       * @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
   */
      click(selector, options = {}) {
      return this.mainFrame().click(selector, options);
      }
       /**
       * @return {!Puppeteer.Frame}
       */
      /**
       * @param {!Protocol.Page.Frame} framePayload`
       */
      _onFrameNavigated(framePayload) {
       const isMainFrame = !framePayload.parentId;
       let frame = isMainFrame ? this._mainFrame : this._frames.get(framePayload.id);
       assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
    // Detach all child frames first.
        if (frame) {
          for (const child of frame.childFrames())
           this._removeFramesRecursively(child);
        }
        if (isMainFrame) {
          if (frame) {
            // Update frame id to retain frame identity on cross-process navigation.
            this._frames.delete(frame._id);
            frame._id = framePayload.id;
          } else {
            // Initial main frame navigation.
            frame = new Frame(this, this._client, null, framePayload.id);
          }
          this._frames.set(framePayload.id, frame);
          this._mainFrame = frame;
        }

据我所知,这是因为我试图查找Page Protocol,但我不知道在那里发生了什么.

This is as far as I have gotten because I've tried to look up the Page Protocol but I can't figure out what happens there.

即使在研究中,任何帮助都将不胜感激.

Any help would be appreciated, even in research.

推荐答案

主要部分发生在 JSHandle 它滚动直到元素在视口中(否则它将不会单击)正在发生

It scrolls until the element is in viewport (otherwise it won't click) which is happening here, then it finds the clickable coordinates on the element using DevTools API here:

async _clickablePoint() {
    const [result, layoutMetrics] = await Promise.all([
      this._client.send('DOM.getContentQuads', {
        objectId: this._remoteObject.objectId
      }).catch(debugError),
      this._client.send('Page.getLayoutMetrics'),
    ]);
    if (!result || !result.quads.length)
      throw new Error('Node is either not visible or not an HTMLElement');
    // Filter out quads that have too small area to click into.
    const {clientWidth, clientHeight} = layoutMetrics.layoutViewport;
    const quads = result.quads.map(quad => this._fromProtocolQuad(quad)).map(quad => this._intersectQuadWithViewport(quad, clientWidth, clientHeight)).filter(quad => computeQuadArea(quad) > 1);
    if (!quads.length)
      throw new Error('Node is either not visible or not an HTMLElement');
    // Return the middle point of the first quad.
    const quad = quads[0];
    let x = 0;
    let y = 0;
    for (const point of quad) {
      x += point.x;
      y += point.y;
    }
    return {
      x: x / 4,
      y: y / 4
    };
}

,最后将鼠标移动到坐标此处并点击此处

and finally it moves the mouse to the coordinate here and clicks on it here

async click(x, y, options = {}) {
    const {delay = null} = options;
    if (delay !== null) {
      await Promise.all([
        this.move(x, y),
        this.down(options),
      ]);
      await new Promise(f => setTimeout(f, delay));
      await this.up(options);
    } else {
      await Promise.all([
        this.move(x, y),
        this.down(options),
        this.up(options),
      ]);
    }
}

使用DevTools API与鼠标进行交互此处

which uses DevTools API to interact with mouse here

async down(options = {}) {
    const {button = 'left', clickCount = 1} = options;
    this._button = button;
    await this._client.send('Input.dispatchMouseEvent', {
      type: 'mousePressed',
      button,
      x: this._x,
      y: this._y,
      modifiers: this._keyboard._modifiers,
      clickCount
    });
}

这篇关于Puppeteer如何处理单击对象/DevTools协议Chromium/Chrome的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆