How can I use previously cached selectors with certain aspects of querySelector() ?

例如,我有这个HTML / JavaScript:

let L1, L2, L3;
L1 = document.querySelector('#L1');

L2 = L1.querySelector('div:nth-child(1)');
L2.classList.add('L2');

L3 = L1.querySelector('div:nth-child(2)');
L3.classList.add('L3');

console.log(L2);
console.log(L3);
<div id="L1">
  <div id="L2">
    <div id="L2a"></div>
    <div id="L2b"></div>
  </div>
  <div id="L3"></div>
</div>
Notice that div#L2b gets the className 'L3' instead of div#L3 getting it.

我真正想做的是这样的事情:

L3 = L1.querySelector('> div:nth-child(2)');

强制querylog() Select 正确的nth-child(2). 例如,在这个不缓存 Select 器的演示中:

let L1, L2, L3;
const $ = document.querySelector.bind(document);
L1 = document.querySelector('#L1');

L2 = L1.querySelector('div:nth-child(1)');
L2.classList.add('L2');

L3 = document.querySelector('div#L1 > div:nth-child(2)');
L3.classList.add('L3');

console.log(L2);
console.log(L3);
<div id="L1">
  <div id="L2">
    <div id="L2a"></div>
    <div id="L2b"></div>
  </div>
  <div id="L3"></div>
</div>

Is there any way this can be done with the L1 cached selector?

在我的真实用例中,L1 Select 器看起来更像是:

const $ = document.querySelector.bind(document);
$('body > div > div#main > div:nth-child(3) > div:nth-child(1) > div > div#L1');

我不敢在必须缓存的15个 Select 器之前输入该字符串.

推荐答案

我相信你想用这:scope selector美元

const L1 = document.querySelector('#L1');
const L3 = L1.querySelector(':scope > div:nth-child(2)');
console.log(L3)
<div id="L1">
  <div id="L2">
    <div id="L2a"></div>
    <div id="L2b"></div>
  </div>
  <div id="L3"></div>
</div>

关于你的意大利面 Select 器:

$('body > div > div#main > div:nth-child(3) > div:nth-child(1) > div > div#L1');

我不确定这是否是为了证明观点的演示,但由于ID必须是唯一的,所以您只需直接指向该ID(标记也是不必要的):

$("#L1")

I see where you're going with $, is to emulate a quasi-jQuery DOM query helper function.
I would suggest instead a better variant in where you can also pass the desired parent:

const el = (sel, par = document) => par.querySelector(sel);

它的用法如下:

// Target an element from document:
const elL1 = el("#L1");
// Target an element from a specific parent:
const elL3 = el(":scope > div:nth-child(2)", elL1); // << notice the second argument

如果出于某种原因,你想确保你试图瞄准的#L1是来自specific website -你可以用途:

// Example making sure to cache `<html>` of Stack Overflow specifically
const elRoot = el(":root:has(meta[content='Stack Overflow'])");
// Cache L1 of specifically "Stack Overflow" website
const elL1 = el("#L1", elRoot);

这比等待网站的设计团队稍微修改一下HTML标记,然后看到您的脚本失败(因为过于具体的spaghetto Select 器)要有更高的存活率.


Javascript相关问答推荐

使用useup时,React-Redux无法找到Redux上下文值

微软Edge Select 间隙鼠标退出问题

按钮未放置在html dis位置

单击子元素时关闭父元素(JS)

使用下表中所示的值初始化一个二维数组

将状态向下传递给映射的子元素

Next.js(react)使用moment或不使用日期和时间格式

如何禁用附加图标点击的v—自动完成事件

如何添加绘图条形图图例单击角形事件

如何将Cookie从服务器发送到用户浏览器

如何在DYGRAPS中更改鼠标事件和键盘输入

使用Ace编辑器对子组件实例的native-element 进行Angular 获取时面临的问题

判断函数参数的类型

如何在脚本编译后直接将RxJ模块导入浏览器(无需Angel、webpack、LiteServer)

MongoDB通过数字或字符串过滤列表

输入数据覆盖JSON文件

如何缩小函数中联合返回类型的范围

带元素数组的Mongo聚合

用内嵌的含selenium的Java脚本抓取网站

使用导航时,路径的所有子组件都必须是路径