【问题标题】:jQuery plugin development - return this.each issuejQuery 插件开发 - 返回 this.each 问题
【发布时间】:2015-01-13 18:07:39
【问题描述】:

我正在尝试开发我的第一个 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");
    ...
  });
  });
};

return 之后放也没什么作用:

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

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

在没有“i”之前,我也不知道是否可以在函数内放置“return”范围之外的任何内容(对我来说似乎无效?):

$.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。

非常感谢。

【问题讨论】:

    标签: jquery jquery-plugins return


    【解决方案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/

    【讨论】:

      【解决方案2】:

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

      • 维护一个内部 jQuery 集合,其中包含当前与插件关联的那些元素。
      • 允许使用“add”方法添加内部集合并使用“remove”方法删除内部集合(均为公共)。
      • 调用插件时不要循环。只需调用 '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',以使其不太可能被其他一些代码使用。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多