不止一种方法……(委托版)

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费额度!

论坛里有人问了一个关于 影响未悬停项目 的问题。 他们想要的效果是,有一个无序列表,当鼠标悬停在列表项上时,所有列表项都会变暗(降低不透明度),除了被悬停的那个。

这可以通过 CSS 使用伪选择器来实现。

ul li:not(:hover) { opacity: 0.5; }

但是我们知道 伪选择器 的跨浏览器支持不是很好。 而且,不透明度 也不好。 jQuery 在缓解跨浏览器问题方面非常出色,所以我认为我可以尝试一下。 在尝试的过程中,我获得了一段不错的学习旅程。

我的第一个想法是,我需要编写一个选择器来选择所有列表项,除了当前被悬停的那个。 我最近因为另一个原因遇到了这个问题,并且为此写了一个代码片段:从选择器中排除 this。 在这个例子中

$("ul li").not(this).css("opacity", "0.5");

我们只需要把它包装在一个悬停函数中。 最明显的方法是

$("li").hover(function() {
  $("li").not(this).css("opacity", 0.5);
}, function() {
  $("li").not(this).css("opacity", 1);
});

但是我一直被教导,像这样绑定事件效率低下,因为 1) 它需要为每个元素单独创建一个事件处理程序,以及 2) 在此代码运行后附加到页面的新元素需要重新绑定。(更不用说,你肯定想缓存上面那个选择器了var $listItems = $("li");).

所以我认为我会直接使用新的 delegate 函数,我们之前在 CSS-Tricks 上已经多次提到过它。 这一点很棒,因为它解决了上面提到的两个问题。 这是我第一次(完全错误的)尝试。

$("ul").delegate("li", "hover", function() {
    $("ul li").not(this).css("opacity", "0.5");
}, function() {
    $("ul li").not(this).css("opacity", "1");
});

不要在家尝试这个,它不会工作。 为什么不行?James Padolsey 提醒我,“hover” 不是一个事件。 它是一个 jQuery 函数,但不是一个真正的事件。 你可以把它与 delegate 一起使用,但不能使用我尝试的那种语法。 Delegate 期望只有三个参数:元素、事件和函数,而不是像我传递的那样四个参数(假设它会知道最后一个函数应该是一个回调/mouseleave)。

然后,下一个最明显的转换变成了这样

$("ul").delegate("li", "mouseenter", function() {
    $("ul li").not(this).css("opacity", "0.5");
}).delegate("li", "mouseleave", function() {
    $("ul li").not(this).css("opacity", "1");
});

这次使用两个 delegate 函数,使用真正的事件来完成任务。 这样可以,但我们可以通过将这两个事件映射到一个 delegate 函数,然后只测试触发了哪种类型的事件来提高效率。David Link 有这个想法

$("ul").delegate("li", "mouseover mouseout", function(e) {
    if (e.type == 'mouseover') {
      $("ul li").not(this).css("opacity", "0.5");
    } else {
      $("ul li").not(this).css("opacity", "1");
    }
});

James Padolsey 有一个更简洁的版本

$("ul").delegate("li", "mouseover mouseout", function(e) {
    $("ul li").not(this).css("opacity", e.type == 'mouseover' ? 0.5 : 1);
});

jQuery 的 live() 函数在这里也是一个不错的选择,但它也有一些怪癖。 事实证明,你可以将“hover”传递给 live,但你仍然只能提供一个函数。 该函数将在 mouseenter 和 mouseleave 事件上触发,并且你必须执行 event.type 测试(如上所述)来确定是哪个事件并相应地做出反应。 感谢 Paul IrishJeffrey Way 提供的这个方法。

还记得最开始的那个 CSS 选择器吗? 我们也可以在 jQuery 中使用它

$("ul li:not(:hover)").css("opacity", "0.5");

真是段旅程啊! 就像网络上的所有事物一样,总有多种方法可以 解决问题