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

Event Handling on multiple instances of the same class - need clarification

本文关键字:事件处理 实例 一类      更新时间:2023-09-26

我需要一些指导来理解为什么这些函数正在做它们正在做的事情......

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

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.)现在,我一直在尝试使所有滑块事件在我单击页面上的任何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 在传播方面发生的事情,但我试图阅读的所有内容都让我感到更加困惑。 谢谢!

这段代码将单击处理程序附加到文档中的所有 .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').click() .slideshow 时起,您已经有另一个处理程序绑定到 元素。 当"on"处理程序完成后,该事件继续向上传播 DOM 树,触发所有向上的单击处理程序,包括您绑定到 .slideshow 元素的那个。 当然,该处理程序也调用_prev() .

如果要停止事件传播,则有两种选择。

  1. 呼叫e.stopPropagation()
  2. 从事件处理程序返回 false(这会告诉 jQuery 停止传播并阻止默认操作)。

你可能会问自己,"click()on('click', ...)有什么区别。 on() 方法允许您使用事件委派。 基本上,这意味着使用附加到一个 DOM 节点的单个事件处理程序来处理许多后代元素上的事件。

例如,假设您有一个包含任意数量的图像的div,并且每当单击图像时都需要执行某些操作。 您可以 (a) 将单击事件处理程序绑定到每个图像,或者 (b) 将处理程序绑定到div,当这些事件在 DOM 树中冒泡时,该处理程序将处理所有图像的所有单击事件。

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

委派还有一个额外的好处,即您可以在容器中添加和删除图像,并且委托将继续工作。