编写第一个jQuery插件:理解这一点

时间:2014-02-02 04:38:25

标签: jquery

我为我的网站制作了一个简单的旋转木马,我想把它带到下一步。我想在一个页面上有几个旋转木马,我想打电话给$('.carousel').swapify()并完成它。

这是我到目前为止所拥有的:

$.fn.swapify = function() {
  var $this = $(this);
  console.log('this is currently: ' + this.selector);

  function advanceSlide() {
    $('.swapify li:first-child').appendTo('.swapify');
  }

  $(this).find('li').click(function() { advanceSlide(); });
}

$(document).ready(function () {
  $('.carousel').swapify();
});

当我与旋转木马互动时,他们都会前进。这很明显,但我不确定如何使交互具体化。我尝试过类似的东西:

$('li:first-child', this).appendTo(this);

我仍在开发我的javascript词汇表,而且它很难谷歌。

编辑:我设置了一个小提琴来说明这个问题http://jsfiddle.net/69FM7/1/

3 个答案:

答案 0 :(得分:2)

IMSoP的答案可能与您的意图相同,但另一种选择是使用委托事件:

$.fn.swapify = (function() {
    function advanceSlide(e) {
        var $carousel = $(e.delegateTarget);
        $carousel.find('li:first-child').appendTo($carousel);
    }

    return function swapify() {    
        this.on("click", "li", advanceSlide);
    };
}());

Fiddle


以下是一些关键概念的快速解释:

  • Immediately Invoked Function Expressions

    IIFE为您提供了一种方法,可以为新的变量和函数创建一个稳定的新范围。我们创建一个函数并立即调用它。

    (function() {
        // new scope here   
    }());
    

    我们在这里使用一个为advanceSlideswapify函数的单个实例创建一个新范围。

  • ClosuresFree Variables

    IIFE的返回值是swapify函数。这个函数是一个闭包 - 它关闭了自由变量advanceSlide。 “自由”在某种意义上,变量advanceSlide“与swapify一起”退出“,当它从函数中返回时 - 它可以自由地超出它的范围。

  • $.fn是jQuery的prototype object的别名。简而言之,这意味着jQuery object的所有实例都可以访问原型定义的函数。

    为清楚起见,$("someselector")将返回jQuery object。我们将IIFE的返回值分配给$.fn.swapify,这将使jQuery对象充满我们的新功能。

  • Delegated Events

    当我们调用我们的swapify帮助程序时,而不是在每个li上绑定事件 - 这是.find("li").on(...)将要做的事情 - 最好将事件绑定在父元素上。 然后让jQuery动态检查事件的target是否与我们关心的集匹配。

    例如,您可能只有少数ul个元素,但每个元素可能包含数百个li个元素。我们可以简单地在父节点上附加一个处理程序,而不需要创建处理程序并在每个节点上附加事件。这样可以最大限度地减少需要绑定的事件处理程序的数量。

  • 使用delegatedTarget property

    中的event object

    最后,当调用我们的事件处理程序时,它将传递event object。这将有几个有用的属性,例如targetcurrentTargetdelegatedTarget。我们使用delegatedTarget来查找我们最初绑定的根元素,并将其分配给$this。然后,你的其余逻辑按照你期望的方式工作。

答案 1 :(得分:1)

您可以通过以下方式实现此目的:

$.fn.swapify = function() {
  $.each($(this), function(index, element) {
    var $this = $(this);

    function advanceSlide() {
       $this.find('li:first-child').appendTo($this);
    }

    $this.find('li').click(function() { advanceSlide(); });
  });
}

由于$this表示swapify get bind的特定选择器。

<强> Demo Fiddle

这将解决您的问题。

答案 2 :(得分:1)

当扩展jQuery原型(jQuery.fn)时,你编写的函数被赋予this 传入的完整jQuery对象,在这种情况下是$('.carousel'),即类carousel的所有元素的集合。因此,涉及this的所有内容都适用于整个集合。

您想要做的事情,以及在这种情况下非常常见的事情,是单独对集合中的每个元素采取行动。为此,您可以使用the .each() function在每个元素上运行相同的函数。每次运行该函数时,this都设置为单个DOM元素 - 而不是jQuery对象,这就是您需要使用$(this)重新包装它的原因。

由于函数有自己的作用域,因此使用var $this = $(this)可以创建“闭包”,它带有特定元素。因为它是在同一范围内声明的,所以函数advanceSlide就是这样一个闭包 - 每次运行函数时,都会为$thisadvanceSlide创建新的变量。

请确保始终使用$this,因为实际的this变量在函数运行时与定义时不同。 (点击处理程序会将其设置为单击的元素。)因此,最好使用不同的变量名称,例如$carousel来记住它引用的对象。

由于advanceSlide已经是本地函数,因此您不需要另一个function() { }包装器,只需将其传递给.click()(或.on())调用。< / p>

所以你最终得到的是as demoed in this JSFiddle

$.fn.swapify = function () {
    // Here, `this` is a jQuery collection with multiple elements in
    this.each(function () {
        // Here, `this` is a single DOM node

        // using `var`, we make a variable bound to this scope
        // while we're at it, we wrap the DOM node with jQuery
        // Rather than $this, I've named the variable something meaningful
        var $carousel = $(this);

        // Declaring a function in the same scope as our var
        // creates a "closure",  which can always see the scope it was created in
        function advanceSlide() {
            // When this runs, it will be in response to a click,
            // and jQuery will set `this` to the element clicked on

            // Our $carousel variable, however, is carried in the closure,
            // so we know it will be the container we want
            $carousel.find('li:first-child').appendTo($carousel);
        }

        // A function in JS is just another kind of object, 
        // so we can pass in advanceSlide like any variable
        $carousel.find('li').on('click', advanceSlide);
    });
}

$(document).ready(function () {
    $('.swapify').swapify();
});