Javascript 是否存在反向查询选择器?
我知道我可以使用querySelector查找文档中的元素Javascript 是否存在反向查询选择器?,javascript,firefox,dom,Javascript,Firefox,Dom,我知道我可以使用querySelector查找文档中的元素 var element = document.querySelector(".myclass") 但是否存在反向查询选择器,以便: var selector = document.inverseQuerySelector(element); Assert.AreEqual(element, document.querySelector(selector)); inverseQuerySelector返回的选择器始终唯一标识指定的元素
var element = document.querySelector(".myclass")
但是否存在反向查询选择器,以便:
var selector = document.inverseQuerySelector(element);
Assert.AreEqual(element, document.querySelector(selector));
inverseQuerySelector返回的选择器始终唯一标识指定的元素?否,因为有许多选择器(可能是无限的)可以选择相同的元素 要使一个函数是可逆的(即使在数学中),它的映射必须是1:1,事实并非如此 顺便说一句,正因为如此,您可以创建一些仅在某些情况下有效的。例如:
function inverseForElementWithUniqueId(element){
return '#' + element.id;
}
var selector = inverseForElementWithUniqueId(element);
Assert.AreEqual(element, document.querySelector(selector)); //True
(看起来确实微不足道的代码)
但正如所说的,由于理论的原因,这只适用于部分案例
但是,它只有在某些情况下才会起作用。您可以创建一个在所有情况下都能起作用的。以两种方式:
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;
}
具有唯一的查询选择器:
第n个孩子(2)>:第n个孩子(5)>:第n个孩子(1)>:第n个孩子(1)>:第n个孩子(3)>:第n个孩子(2)>:第n个孩子(6)>:第n个孩子(1)>:第n个孩子(1)>:第n个孩子(1)>:第n个孩子(1)>:第n个孩子(2)
<a id="y" class="vote-up-off" title="This answer is useful">up vote</a>
html>body>div>div>div>div>div>div>table>tbody>tr>td>div>a[id=“y”][class=“投票结束”][title=“此
答案很有用“]
通过以下方法测试溶液是否正确:
// e is an element and e must exist inside the page
document.querySelector( getMyPathByIndex(e)) === e &&
document.querySelectorAll( getMyPathByIndex(e)).length === 1
// e is an element and e must exist inside the page
document.querySelector( myUniqueQuerySelector(e)) === e &&
document.querySelectorAll( myUniqueQuerySelector(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( getMyPathByIndex(e)) === e &&
document.querySelectorAll( getMyPathByIndex(e)).length === 1
// e is an element and e must exist inside the page
document.querySelector( myUniqueQuerySelector(e)) === e &&
document.querySelectorAll( myUniqueQuerySelector(e)).length === 1
我混合了建议的两种解决方案,以获得人类可读的结果,如果有几个类似的兄弟姐妹,则给出正确的元素:
功能elemToSelector(elem){
常数{
标记名,
身份证件
类名,
返回节点
}=元素;
如果(标记名=='HTML')返回'HTML';
设str=标记名;
str+=(id!='')`${id}`:'';
if(类名){
const classes=className.split(/\s/);
for(设i=0;i${str}`;
}
使用以下各项进行测试:
//在navigator Devtools的“元素”选项卡中选择一个元素,或替换$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)
编辑:我刚刚发现了这个包请尝试“not:”,如下面的问题所示回答:也许inverseQuerySelector是个坏名字。我想我所追求的是生成唯一标识文档中给定元素的选择器,而不是与任何可能的选择器相反的选择器。鉴于此,我扩展了答案您可以基于类、id和dom位置构建一个完整的查询,但我不认为这对真正好的答案有什么好处!在第一个选项中,如果元素具有id或其他唯一属性,是否可以缩短查询?@Giuppox如果您有id,查询选择器为
#
,如果您具有唯一属性或具有唯一值的属性,则可以使用标记[attribute='regular-expresion']
。更多信息请点击这里()