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

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

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

$("div").myPlugin(); 

来源:

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

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

因为一旦它变成“返回this.each”,它就会被连接多次,就像这个循环中的元素一样多……

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

在返回后把它放在一起并没有做任何事情:

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

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

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

我是jQuery的新手,我不确定我是否正确理解文档,我想知道最好不要在这里使用return吗? 请注意,此插件可以使用1个元素,但通常会有更多的div而不是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 ie $(this) return this; }; })(jQuery, window); $('div').myPlugin(); console.log($('div').map(function(){ return this.className; }).get()); 

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

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

  • 维护一个内部jQuery集合,其中包含当前与该插件相关联的元素。
  • 允许使用“添加”方法添加内部集合,并通过“删除”方法(公共)进行耗尽。
  • 调用插件时不要循环。 只需调用’add’方法并返回 – 不需要.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'以使其更不可能被其他一些代码使用。

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