jQuery插件开发 - 返回this.each问题

时间:2014-11-16 21:39:52

标签: jquery jquery-plugins return

我正在尝试开发我的第一个jQuery插件。基本上它将类附加到站点上的各种元素,然后在用户滚动时更改它(我正在计算偏移量等等)。而且我觉得我已经用这个打了一堵墙。

以下是我启动插件的方法:

$("div").myPlugin();

来源:

$.fn.myPlugin = function() {
  return this.each(function() {
   $(this).addClass("something-" + i);
   i++;
  });
};

有人可以解释一下如何在我的插件中使用$(window).scroll吗?

因为一旦它进入“return this.each”,它就会被连接多次在这个循环中的元素......

$.fn.myPlugin = function() {
  return this.each(function() {
   $(this).addClass("something-" + i);
   i++;

   $(window).scroll( function() { <!-- here it not only attaches itself x-times but i is always the same -->
    ...
    $(".something-" + i).addClass("active");
    ...
  });
  });
};

在返回后放置它不会做任何事情:

$.fn.myPlugin = function() {
  return this.each(function() {
   $(this).addClass("something-" + i);
   i++;
  });

  $(window).scroll( function() { <!-- doesn't seem to work -->
    ...
    $(".something-" + i).addClass("active");
    ...
  });
};

在没有“我”之前,我也不知道我是否可以在函数内部放置“返回”范围之外的东西(对我来说似乎没有用?):

$.fn.myPlugin = function() {
  $(window).scroll( function() { <!-- there is no "i" yet -->
    ...
    $(".something-" + i).addClass("active");
    ...
  });

  return this.each(function() {
   $(this).addClass("something-" + i);
   i++;
  });
};

我是jQuery的新手,我不确定我是否正确理解文档,我想知道最好不要在这里使用return吗?请注意,此插件可以使用1个元素,但通常会有更多的div而不是1。

非常感谢。

2 个答案:

答案 0 :(得分:1)

这个怎么样:

(function($, window, undefined){

    $.fn.myPlugin = function() {

        // bind the scroll event listener once
        $(window).scroll(function(){ 
            console.log('scroll');
        });

        // iterate your plugin elements
        // use index passed by the .each callback:
        this.each(function(i, el){   
            $(el).addClass('something-' + i);
        });

        // return your jQuery object to allow chaining on your plugin
        // note that (this instanceof jQuery) === true, so there is no need
        // to pass it to the jQuery function i.e. $(this)
        return this; 

    };

})(jQuery, window);

$('div').myPlugin();

console.log($('div').map(function(){ return this.className; }).get());

http://jsfiddle.net/yw0q5hn7/2/

答案 1 :(得分:0)

可能有几种方法可以编写插件。以下是最合适的特征:

  • 维护一个内部jQuery集合,其中包含当前与该插件关联的元素。
  • 允许使用“添加”方法添加内部集合,并通过“删除”方法(公共)耗尽。
  • 调用插件时不要循环。只需调用'添加'方法并返回this - 不需要.each()(至少,不要公开)。
  • 仅在jQuery集合不为空时附加滚动处理程序 - 监视内部集合的长度并相应地附加/分离。

请注意,这些特性在编码时将采用非常非典型的插件模式。因此,这可能不是您的第一个插件选择的最佳问题。

然而,这里......

(function($, window, undefined) {
    // Private vars
    var pluginName = 'myPlugin',
        jqCollection = $(),
        events = {
            scroll: 'scroll.' + pluginName
        },
        className = pluginName + 'active',
        timeout;
    // Private functions
    function scroll() {
        if(jqCollection.closest('body').length === 0) { 
            //This is advisable in case some other javascript/DOM activity has removed all elements in jqCollection.
            // Thanks to selected answer at :
            // http://stackoverflow.com/questions/4040715/check-if-cached-jquery-object-is-still-in-dom
            jqCollection = $();
            $(window).off(events.scroll);
        } else {
            jqCollection.addClass(className);
            clearTimeout(timeout);
            timeout = setTimeout(function() {
                jqCollection.removeClass(className);
            }, 100);
        }
    }
    // Public methods
    methods = {
        add: function(jq) {
            jqCollection = jqCollection.add(jq);
            if(jqCollection.length > 0) {
                $(window).off(events.scroll).on(events.scroll, scroll)
            }
        },
        remove: function(jq) {
            jqCollection = jqCollection.not(jq);
            if(jqCollection.length === 0) {
                $(window).off(events.scroll);
            }
        }
    };
    // The actual plugin
    $.fn[pluginName] = function(method) {
        method = method || 'add';
        if(methods[method]) {
            methods[method](this);
        } else {
            console.log('jQuery plugin ' + pluginName + 'has no method: ' + method);
        };
        return this;
    };
})(jQuery, window);

按如下方式关联所选元素:

$(selector).myPlugin();
//or
$(selector).myPlugin('add');

如下所示取消选定的元素:

$(selector).myPlugin('remove');

<强> DEMO

请注意,我已将类名更改为pluginName + 'active',以使其更少被其他代码使用。

正如我所说,这是一种方法。也许你可以完全考虑改进或其他方式。