Как получить className, Id и nth: child (n) элемента, чтобы быть хорошим стабильным querySelector? - PullRequest
0 голосов
/ 25 февраля 2019

Я получаю элемент по координатам X, Y.Я хотел бы, чтобы мой конечный результат строки выглядел как Inspect -> copySelector:

body> div.layout.slidein-page-container> main> div.ng-scope> section.wrapper.wrapper--canvas> div> div> div> div: nth-child (2)

Так что будет хорошей строкой queryString оценить JSHandle из него.

Вот мой код:

let chosenElement = await page.evaluate((payload) => {
        return document.elementsFromPoint(payload.data.x, payload.data.y)
            .map((o) => {
                if (o.id) {
                    return o.id;
                } else if (o.className) {
                    if (o.className.includes(' ')) {
                        return o.tagName.toLowerCase() + '.' + o.className.split(' ').join('.');
                    } else {
                        return o.tagName.toLowerCase() + '.' + o.className;
                    }
                } else {
                    return o.tagName.toLowerCase();
                }
            }).reverse().join(' > ');
    }, payload);

Так что в настоящее время я проверяю только className и Id, но я хочу уточнить это.

Первая подсказка, которая мне нужна, - как проверить, если элементнапример, nth-child (2)?

Можете ли вы помочь мне с лучшим решением, пожалуйста

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Я надеюсь, что это поможет некоторым другим парням

  let chosenElement = await page.evaluate((payload) => {
        return document.elementsFromPoint(payload.data.x, payload.data.y)
            .map((o) => {
                let sibArr = Array.from(o.parentNode.children).filter(i => i.tagName === o.tagName);
                if (sibArr.indexOf(o) > 0) {
                    let oIndex = sibArr.indexOf(o);
                    return `${o.tagName.toLowerCase()}:nth-child(${oIndex + 1})`;
                } else if (o.id) {
                    return '#' + o.id;
                } else if (o.className) {
                    return `${o.tagName.toLowerCase()}.${Array.from(o.classList).join('.')}`
                } else {
                    return o.tagName.toLowerCase();
                }
            }).reverse().filter(e => !e.includes('html')).join(' > ');
    }, payload);

Это соответствует желаемому результату:

body > div:nth-child(3) > header.layout__header.slidein-page > div.container > nav.nav-bar > ul.nav-bar__nav > li:nth-child(3) > a
0 голосов
/ 26 февраля 2019

вы можете преобразовать родительские дочерние элементы элемента из HTMLCollection в массив с помощью:

Array.from(o.parentElement.children)

найти индекс вашего элемента:

const oIndex = Array.from(o.parentElement.children).indexOf(o);

вернуть селектор:

return `${o.tagName}:nth-child(${oIndex + 1})`;

вам нужно добавить 1, потому что nth-child начинается с 1, где индексы в массиве начинаются с 0;

Кстати:

  • вы забыли добавить # перед идентификатором при создании селектора.
  • вам не нужно указывать тэг в вашем селекторе в нижнем регистре
  • если у объекта есть className, вы можете просто вернуть ${o.tagName}.${Array.from(o.classList).join('.')}
...