2014-11-16 50 views
0

我想開發我的第一個jQuery插件。基本上,它將類添加到網站上的各種元素,然後在用戶滾動時對其進行更改(我正在計算偏移和什麼)。我認爲我已經用這個打了一堵牆。jQuery插件開發 - 返回這個問題

下面是如何啓動插件:

$("div").myPlugin(); 

和源:

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

可能有人請解釋如何在我的插件使用$(窗口).scroll?

因爲一旦它變成「迴歸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"); 
    ... 
    }); 
}; 

而且之前有沒有「我」 S,也是我不知道我是否可以把任何東西「返回」範圍之外的函數內(似乎沒有有效的給我?):

$.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個元素,但通常會有比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 i.e. $(this) 
     return this; 

    }; 

})(jQuery, window); 

$('div').myPlugin(); 

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

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

0

可能有幾種方式來寫插件。以下是最合適的特徵:

  • 維護一個包含當前與插件關聯的元素的內部jQuery集合。
  • 允許使用'add'方法添加內部集合,並通過'remove'方法(均爲public)來耗盡內部集合。
  • 插件調用時不要循環。只需調用'add'方法並返回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',以使其他代碼不太可能被使用。

正如我所說,這是一個辦法。也許你可以完全想到改進或其他方式。