我知道我可以使用querySelector来定位文档中的元素
var element = document.querySelector(".myclass")
但是是否存在反向querySelector:
var selector = document.inverseQuerySelector(element);
Assert.AreEqual(element, document.querySelector(selector));
inverseQuerySelector的返回选择器总是唯一标识指定的元素吗?
答案 0 :(得分:2)
不,因为有很多选择器(可能是无限的)可以选择相同的元素。
对于一个可逆的函数(即使在数学中),它的映射必须是1到1,但事实并非如此。
BTW,因此,您可以创建一些仅在某些情况下 的作品。例如:function inverseForElementWithUniqueId(element){
return '#' + element.id;
}
var selector = inverseForElementWithUniqueId(element);
Assert.AreEqual(element, document.querySelector(selector)); //True
(代码确实可能看起来微不足道)
但正如所说,由于这个理论,这只适用于一部分案例。
但是,它有时只会起作用
答案 1 :(得分:1)
您可以创建一个适用于所有情况的。有两种方式:
解决方案如下:
function getMyPathByIndex(element){
if(element == null)
return '';
if(element.parentElement == null)
return 'html'
return getMyPathByIndex(element.parentElement) + '>' + ':nth-child(' + getMyIndex(element) + ')';
}
function getMyIndex(element){
if(element == null)
return -1;
if(element.parentElement == null)
return 0;
let parent = element.parentElement;
for(var index = 0; index < parent.childElementCount; index++)
if(parent.children[index] == element)
return index + 1;
}
例如,元素:
<a id="y" class="vote-up-off" title="This answer is useful">up vote</a>
只需在控制台中输入
,即可在此页面中获取此元素document.querySelector('a[title="This answer is useful"]');
有唯一的querySelector :
HTML&GT;:第n个孩子(2)&GT;:第n个孩子(5)&GT;:第n个孩子(1)&GT;:第n个孩子(1)&GT;:第n个孩子(3)&GT; :第n个孩子(2)&GT;:第n个孩子(6)&GT;:第n个孩子(1)&GT;:第n个孩子(1)&GT;:第n个孩子(1)&GT;:第n个孩子( 1)&GT;:第n个孩子(1)&GT;:第n个孩子(2)
之前使用相同的元素唯一的querySelector :
HTML&GT;主体&GT; DIV&GT; DIV&GT; DIV&GT; DIV&GT; DIV&GT; DIV&GT;表&gt; TBODY&GT; TR&GT; TD&GT; DIV&gt;一种[ID = “Y”] [类= “投票向上客”] [标题=“此 答案很有用“]
测试解决方案是否正确:
// e is an element and e must exist inside the page
document.querySelector( getMyPathByIndex(e)) === e &&
document.querySelectorAll( getMyPathByIndex(e)).length === 1
代码解决方案如下:
function convertAttributesToQuerySelector(element){
var tagName = element.tagName.toLowerCase();
var result = tagName;
Array.prototype.slice.call(element.attributes).forEach( function(item) {
if(element.outerHTML.contains(item.name))
result += '[' + item.name +'="' + item.value + '"]';
});
return result;
//["a[id="y"]", "a[class="vote-up-off"]", "a[title="This answer is useful"]"]
}
function getMyPath(element){
if(element.parentElement.tagName == 'HTML')
return 'html';
return getMyPath(element.parentElement) + '>' + element.parentElement.tagName.toLowerCase() ;
//"html>body>div>div>div>div>div>div>table>tbody>tr>td>div"
}
function myUniqueQuerySelector(element){
var elementPath = getMyPath(element);
var simpleSelector = convertAttributesToQuerySelector(element);
return elementPath + '>' + simpleSelector;
}
您可以随时测试解决方案是否正确:
// e is an element and e must exist inside the page
document.querySelector( myUniqueQuerySelector(e)) === e &&
document.querySelectorAll( myUniqueQuerySelector(e)).length === 1
答案 2 :(得分:0)
我混合了提出的 2 个解决方案,以获得人类可读的结果,如果有几个类似的兄弟姐妹,它会给出正确的元素:
function elemToSelector(elem) {
const {
tagName,
id,
className,
parentNode
} = elem;
if (tagName === 'HTML') return 'HTML';
let str = tagName;
str += (id !== '') ? `#${id}` : '';
if (className) {
const classes = className.split(/\s/);
for (let i = 0; i < classes.length; i++) {
str += `.${classes[i]}`;
}
}
let childIndex = 1;
for (let e = elem; e.previousElementSibling; e = e.previousElementSibling) {
childIndex += 1;
}
str += `:nth-child(${childIndex})`;
return `${elemToSelector(parentNode)} > ${str}`;
}
测试:
// Select an element in Elements tab of your navigator Devtools, or replace $0
document.querySelector(elemToSelector($0)) === $0 &&
document.querySelectorAll(elemToSelector($0)).length === 1
这可能会给你一些类似的东西,它有点长,但它是可读的,而且总是有效:
HTML > BODY:nth-child(2) > DIV.container:nth-child(2) > DIV.row:nth-child(2) > DIV.col-md-4:nth-child(2) > DIV.sidebar:nth-child(1) > DIV.sidebar-wrapper:nth-child(2) > DIV.my-4:nth-child(1) > H4:nth-child(3)
编辑:我刚刚找到包 unique-selector