CSS 特异性计数器

问题描述

因此 CSS 特异性 rules 规定 id 是最强大的,然后是类,然后是标签名称,然后是 *。

所以 #id > .class > div > *

如果我提供一串 CSS 选择器,我想要做的是为每个人获得一个“评级”。

假设我有一个特殊性数组 = [#id,.class,tagname]

span 应该返回 [0,1]

body p 应该返回 [0,2]

.red .orange 应该返回 [0,2,0]

menu .item #checkout.active 应该返回 [1,1]

我试过这段代码,但肯定有问题:

function compare(a) {
    const comparisonoperators = ["#","."," "];
    const arating = [];

    for (let x = 0; x < comparisonoperators.length; x++) {
        arating[x] = a.includes(comparisonoperators[x])
            ? a.split(comparisonoperators[x]).filter((x) => x).length
            : 0;
    }

    console.log(arating);
}

compare("menu .item #checkout.active");
// returns [2,3,3]

对此有什么想法吗?

解决方法

我采用了与您不同的方法来解决此问题。

function compare(a) {
    var items = a.split([' ']);
    var aRating = [0,0];
    items.forEach(function(i) {
        //case 1
        if(i.split('#').length > 1) {
            aRating[0] = aRating[0] + (i.split('#').length - 1)
        }
        //case 2
        if(i.split('.').length > 1) {
            aRating[1] = aRating[1] + (i.split('.').length - 1)
        }
        //case 3
        if(!i.startsWith('#') && !i.startsWith('.')) { 
            aRating[2] = aRating[2] + 1
        }
        
    });
    console.log(aRating);
}

最初,我根据空格拆分字符串。这给出了要检查的元素总数。然后我将遍历该数组中的每个项目以确定并计算选择器的数量。

在情况 1 中,如果项目包含 ID,则其长度将大于 1。例如,#myId。如果我根据 # 拆分它,那么我将在数组中获得 2 个项目。我正在使用它来确定它是否包含 ID。在这种情况下,它是正确的,所以我将 aRating 数组增加 1。如果它不是 ID,那么它的长度将始终为 1,因为它无法拆分。

相同的逻辑适用于 css class 的情况 2。

案例 3 略有不同。如果字符串不以 # 或 '.' 开头,则它必须是标记名。