对同一类的多个实例进行事件处理 - 需要澄清

时间:2013-01-25 23:16:34

标签: javascript jquery

我需要一些指导来理解为什么这些功能正在做他们正在做的事情......

1。)在我的网页上,我有三个不同的面板,它们使用Slider功能,它创建一个无序列表,其中包含使用下一个和上一个锚链接的滑块功能。请参阅以下代码:

function Slider(id) {
    var _this = this;
    this.id = id;
    if (!id) return false;
    this.index = 0;
    this.slider = $(this.id);
    this.length = this.slider.children().length;
    this.width = $(this.id).outerWidth();
    this.totalWidth = this.length * this.width;
    $(id).addClass('slideWrapper').wrap('<div class="slideViewport">').after('<div class="sliderNav"><a href="#" class="prev">Previous</a><a href="#" class="next">Next</a></div>').css({
      'width': this.totalWidth
  }).children().addClass('slide').css({
      'width': this.width
  });

  $('.slideViewport a.next').click(function(e) {
    e.preventDefault();
    return _this.next();
  });

  $('.slideViewport a.prev').on(function(e) {
    e.preventDefault();
    return _this.prev();
  });
}

如果我尝试在页面上运行多个Slider实例,单击.next锚点将使单击的元素及其下方的任何元素更多地显示在幻灯片中的下一个列表元素中。转到第二个面板将导致除第一个面板之外的所有面板运行,第三个面板导致除第一个和第二个面板之外的所有面板运行,等等。我原本希望处理程序仅针对我单击的事件运行,而不是所有实例之后的课程,因为我在我的活动中使用this。任何关于这里发生的事情的解释都会非常有用。

2。)现在,我一直试图让所有Slider事件在我点击页面上的任何a.next锚点时运行next(),而不是只运行一个事件我点击过它的主播。我发现这段代码有效:

$('.slideshow').on("click", "a.next", function(e) {
   e.preventDefault();
   return _this.prev();
});

但事实上我说过,我不确定为什么会这样。我的理解是JQuery只是想查看a.next锚是否被点击,然后将处理函数传递给$('。slideshow')选择器,这使我假设它正在选择$的所有实例( 'slideshow')并为所有这些运行.next()函数。这是考虑它的正确方法吗?

3.。)为什么以下代码片段会导致所有幻灯片显示两次运行next()函数,而不是一次?我真的不喜欢这不会返回任何东西,所以我真的不想使用这个特定的代码,但我只是想更好地理解它......

$('.slideViewport a.next').on("click", function(e) {
   e.preventDefault();
   $('.slideshow').each(function() {
     _this.prev();
   }
});

非常感谢帮助理解这些代码。在这种情况下,我真的希望能够更好地理解DOM中传播的内容,但是我尝试阅读的所有内容都让我感到更加困惑。谢谢!

1 个答案:

答案 0 :(得分:2)

这段代码将点击处理程序附加到文档中的所有 .slideshow元素。

$('.slideshow').click(function(e) {
    e.preventDefault();
    return _this.prev();
});

您可能想要的是将处理程序仅附加到作为滑块后代的.slideshow元素:

this.slider.find('.slideshow').click(function(e) {
    // ... handle event here ...
});

现在,关于你的on()陈述:

$('.slideshow a.next').on("click", function(e) {
   e.preventDefault();
   $('.slideshow').each(function() {
     _this.prev();
   }
});

您在此处所做的是将click事件处理程序绑定到所有.slideshow a.next元素,并且处理程序执行的操作是对所有元素运行_prev()。但从调用.slideshow时起,您已经有另一个绑定到$('.slideshow').click()元素的处理程序。当“on”处理程序完成时,事件继续向上传播DOM树,触发所有单击处理程序,包括绑定到.slideshow元素的处理程序。当然,该处理程序也会调用_prev()

如果您想停止事件传播,您有两种选择。

  1. 致电e.stopPropagation()
  2. 从事件处理程序返回false(这告诉jQuery停止传播并阻止默认操作)。
  3. 您可能会问自己,“click()on('click', ...)之间有什么区别。on()方法允许您使用Event Delegation。基本上,这意味着使用单个事件处理程序附加到一个DOM节点以处理许多后代元素上的事件。

    作为一个例子,假设你有一个div,其中有一些任意数量的图像,你需要在点击图像时做一些事情。您可以(a)将click事件处理程序绑定到每个图像,或者(b)将处理程序绑定到div,该div将处理所有图像的所有单击事件,因为这些事件会冒出DOM树。

    $('#imageDiv').on('click', 'img', function(evt) {
        // ... "this" is the image that was clicked ...
    });
    

    委派具有额外的好处,您可以从容器中添加和删除图像,代理将继续工作。