4

最近在编写脚本时,我发现了 Sizzle 如何属性一起使用href特殊细微差别。具体来说,在 上使用属性选择器href,Sizzle 将使用实际的属性值:

// Will not find <a href="index.html">...
$('a[href="http://www.example.com/index.html"]')

Sizzle 使用.getAttribute()代替elem.href(或更准确地说elem['href'],就像Sizzle 在大多数情况下所做的那样);elem.href将提供完全限定的 URL。

为了进一步理解这一点,我创建了一个小提琴来尝试不同形式的 URL在测试过程中,我发现了将 equal 设置href为自身的(明显的)“解决方案” :

$('a').each(function(){
    this.href = this.href;
});

毫不奇怪,它会更新元素以反映所this.href提供的完全限定 URL。我发现还有其他方法可以工作(任何更新href元素属性的方法),但它们只是将上述方法移植到其他形式,或涉及类似.filter()(demo)的内容:

var matches = $('a').filter(function(){
    var window_location = 'http://example.com/services.html';
    return window_location == this.href;
});

我这么说的原因是,el.href = el.href在选择之前做在某种意义上是一种解决方法(我认为这不是一个很好的选择)。例如,对一组元素进行检查以查找是否有任何包含指向当前 URL(或另一个 URL)的匹配链接,如果可以的话,这样做会更简单:

$links.not('[href="' + window.location.href + '"]')

有没有办法做到这一点,而不必诉诸“更新”属性,或编写额外的代码来管理检查?有没有一种我忽略的方法不涉及修改 Sizzle 的工作方式^

^ 注意:与仅添加:相比,修改实际源代码将是一个(坏)主意expression

$.extend($.expr[':'], {
    url: function(elem, i, match){
        return elem.href === match[3];
    }
});

var $matched = $('a:url(http://test.com/index.html)');

http://jsfiddle.net/yt2RU/

(顺便说一句,在 Sizzle 中是否还有其他具有类似非典型行为的属性?)

4

1 回答 1

3

我相信我已经得到了这个问题的答案...

使用任一expression

jQuery.extend(jQuery.expr[':'], {
    url: function(elem, i, match){
        return elem.href === match[3];
    }
});

var $matched = jQuery('a:url(http://test.com/index.html)');

http://jsfiddle.net/yt2RU/

或者,正如评论中指出的那样,$.filter()可以使用:

var $matched = $('a').filter(function(){
    if (this.href == 'http://test.com/index.html') {
        return true;
    }
    return false;
});

http://jsfiddle.net/dMuyj/

querySelector()并且 jQuery 只有在原生且不可用时才回退到 Sizzle querySelectorAll(),并且这两者的工作方式与 jQuery 的选择器引擎相同(不足为奇)。

总和是,如果您需要这种类型的选择器,则需要表达式或过滤器,并elem.href用于比较,而不是getAttribute().

于 2012-03-07T01:05:04.437 回答