Google chrome 如何从所选元素创建查询选择器?
在GoogleChrome中,尤其是现在有了自定义元素,现在手工选择和添加元素变得非常麻烦,尽管浏览器已经知道了它的全部路径。或者是否有一种方法可以导致为我正在检查的元素选择查询 情况: chrome能告诉我什么: chrome无法为我创建的内容:Google chrome 如何从所选元素创建查询选择器?,google-chrome,chromium,Google Chrome,Chromium,在GoogleChrome中,尤其是现在有了自定义元素,现在手工选择和添加元素变得非常麻烦,尽管浏览器已经知道了它的全部路径。或者是否有一种方法可以导致为我正在检查的元素选择查询 情况: chrome能告诉我什么: chrome无法为我创建的内容: 在构建chrome扩展时,我发现在返回页面时需要唯一地定位元素。为此,我需要为所选元素创建一个查询字符串自定义上下文菜单单击 在寻找解决方案的过程中,我发现了这个悬而未决的问题 由于我找不到现成的解决方案或API来完成这项任务,所以我编写了以下函数。
在构建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。否则返回查询字符串
示例结果
工作原理
代码假定页面格式正确,ID必须是唯一的
查询字符串将尝试以id(例如elementId)开头,但如果元素没有id,则查询将使用标记和类名。我的班级
标记和类名不能唯一标识元素。为了检查查询是否唯一,使用查询字符串从父元素查询DOM
如果需要,查询字符串将使用元素位置来优化查询div.my-class:nth-child2。不幸的是,这使得结果查询字符串对元素顺序的更改不敏感
查询字符串沿着每个父级建立,直到它找到具有id的元素或不再有父级为止
最后一步使用查询查看查询是否找到了正确的元素,如果查询成功,则返回查询
代码
"#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
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) { }
}