有什么方法可以 select CSS class 和 DOM 中不存在的 JS?

Are there any ways to select a CSS class with JS that doesn't exist in DOM?

是否可以 select CSS classregistered 仅在其文件中,不存在于 [=] 中的 JS 37=]?

var elem = document.getElementsByClassName('class2')[0],
    getStyle = window.getComputedStyle(elem),
    value = getStyle.getPropertyValue('top');
console.log(value);
// Can't get the value of class2 because it doesn't exist in DOM. 
.class1 {
  top: 10px;
}
.class2 {
  top: 20px;
}
<div class="class1">
  top
</div>

像这个例子, select 和 .class1 没有问题,因为它存在于 DOM 元素中。

但我想访问 DOM 中不存在的 .class2

有没有办法做到这一点?

访问此类元素的唯一可能方法是事先引用它或它的父元素之一。通常的方法是使用从 document.createElement 创建的元素引用,或者通过创建元素的任何方式:

const element = document.createElement('div');
element.className = 'class2';

// element is not attached to the DOM, but you can still reference it here

// you can also retrieve elements created by assigning to the innerHTML of another element:
element.innerHTML = '<div class="class2"></div>';
const element2 = element.children[0];

// element2 is not attached to the DOM, but you can still reference it here

如果看不到元素的创建位置,这些方法将不起作用。在这种情况下,您唯一的其他选择是在创建元素的脚本运行 之前 对可以创建元素的各种方法进行 monkeypatch,(例如 createElementinnerHTML setter、outerHTML setter 等)但这几乎总是一个非常糟糕的主意,除非没有其他选择(比如如果您正在编写用户脚本)。

XY 问题在这里...您不是想要获取元素,而是样式表中设置的值。

即使这可能是可能的(它是,但非常复杂),但该方法存在一个很大的缺陷:因为存在 CSS 规则并不意味着它会得到应用.

例如,在您的情况下,.class2 规则确实存在并且处于活动状态,但是,由于没有元素匹配此规则,它不会有任何效果。
同样,即使一个元素确实匹配这条规则,它也很可能被其他规则覆盖:

console.log(
  getComputedStyle(
    document.querySelector('.class2')
  ).getPropertyValue('top')
); // "10px"
#foo { top: 10px };
.class2 { top: 50px; }
<div class="class2" id="foo"></div>

所以,是的,您可以获得 CSS 规则的设定值:

const matching_rules = [...document.styleSheets].reduce((matched, sheet) => {
  [...sheet.cssRules].forEach( r => {
      if(r.selectorText && r.selectorText.includes('.class2'))
        matched.push(r.style.top);
  });
  return matched;
}, []);
console.log(matching_rules);
.class2 { top: 50px; }

但是再一次,这真的没有用,大多数时候,你只需要在你的元素附加到 DOM 后调用 getComputedStyle(调用它是没有用的之前,因为没有 CSS 规则应用于未显示的元素。

const elem = document.createElement('div');
elem.classList.add('class2');
console.log('matches:', elem.matches('.class2')); // true
const comp = getComputedStyle(elem);
console.log('computed top:', JSON.stringify(comp.getPropertyValue('top'))); // "" (the default)
.class2 {
  top: 50px;
}