【问题标题】:How to create a query selector out of a selected element?如何从选定元素中创建查询选择器?
【发布时间】:2020-05-10 08:31:49
【问题描述】:

在 google chrome 中,尤其是现在使用自定义元素,如今手动选择和元素变得非常麻烦,即使浏览器已经知道它的整个路径。 或者有没有一种方法可以为我正在检查的元素选择查询?

情况:

chrome 能告诉我什么:

什么 chrome 无法为我创建 AFAIK:

【问题讨论】:

    标签: google-chrome chromium


    【解决方案1】:

    在构建 chrome 扩展时,我发现在返回页面时需要唯一地定位元素。为此,我需要为选定元素创建一个查询字符串(自定义上下文菜单单击)

    在寻找解决方案时,我发现了这个未回答的问题。

    由于我找不到现成的解决方案或 API 来执行该任务,因此我编写了以下函数。它未经野外测试,非常粗糙且准备就绪(使用糟糕的节点遍历技术)。我以这种状态发布它以免我忘记并且这个问题仍然没有答案。

    为元素创建查询字符串

    一个用于构建查询字符串的函数,该字符串将从元素的引用中唯一地定位一个元素。

    const querytStr = createQueryStringForElement(myElement); // return string or undefined
    if (querytStr) {
        const element = document.querySelector(queryStr);
        console.log(element === myElement); // expected result true
    }
    

    如果函数未能创建唯一定位元素的查询,则返回undefined。否则返回查询字符串。

    示例结果

    "#editor > div.ace_scroller > div.ace_content > div.ace_layer.ace_text-layer > div.ace_line:nth-child(45) > span.ace_punctuation.ace_operator"
    
    
    "#buttons"                             // A UI container
    "#buttons > div.buttons"               // A sub UI container
    "#buttons > div.buttons:nth-child(2)"  // A button element by position
    "#buttons > div.buttons:nth-child(3)"  // A button element by position
    

    工作原理

    • 代码假定页面格式正确(id 必须是唯一的)。

    • 查询字符串将尝试以id 开头,例如"#elementId",但如果元素没有id,则查询将使用标签和类名。例如"div.my-class"

      标签和类名不能唯一标识元素。为了检查查询是否唯一,查询字符串用于从父元素查询 DOM。

      如果需要,查询字符串将使用元素位置来优化查询"div.my-class:nth-child(2)"。不幸的是,这使得生成的查询字符串对元素顺序的变化不敏感。

    • 查询字符串沿每个父级构建,直到找到具有id 的元素或没有更多父级为止。

    • 最后一步使用查询来查看查询是否找到正确的元素,如果成功则返回查询。

    代码

    function createQueryStringForElement(element) {
        const getElementSel = element => {
            const tName = element.tagName.toLowerCase();
            var i = 0, str = element.id ? "#" + element.id : sel = tName;
            if (str.includes("#")) { return str}
            str += element.classList.length ? "." + [...element.classList.values()].join(".") : "";
            if (element.parentElement) {
                const res = element.parentElement.querySelector(str);
                if (res !== element) {
                    while (i < element.parentElement.children.length) {
                        if (element.parentElement.children[i] === element) {
                            i > 0 && (str += ":nth-child(" + (i + 1) + ")" );
                            break;
                        }
                        i++;
                    }
                }
            }
            return str;
        }
        const queryPath = [];
        const original = element;
        do {
            const subQuery = getElementSel(element);
            queryPath.push(subQuery);
            if (subQuery[0] === "#") { break }
            element = element.parentElement;
        } while (element);
        const query = queryPath.reverse().join(" > ");
        try {
            const els = document.querySelector(query);
            if (els === original) { return query }
        } catch(e) { }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      相关资源
      最近更新 更多