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());
编写插件可能有几种方法。 以下是最合适的特征:
- 维护一个内部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'
以使其更不可能被其他一些代码使用。
正如我所说,这是一种方法。 也许你可以完全考虑改进或其他方式。