jQuery插件回调$this不能返回元素

jQuery Plugin Callback $this can't return element

本文关键字:不能 返回 元素 this 插件 回调 jQuery      更新时间:2023-09-26

我正在学习编写一个迷你jQuery插件工具。

我的插件是帮助用户检查用户鼠标滚轮是否向上滚动或向下滚动触发回调函数。

我有一个四个div,当我的鼠标指针悬停在它和鼠标滚轮向上滚动,插件回调将改变这个div的背景颜色。

不幸的是,我的回调函数$this不能指向这个元素。我需要一些帮助。

    body {background: #2A2B30;}
    .wrapper {margin-top: 100px;}
    .wrapper div.content {border-radius: 7px; border: 1px solid #000; min-height: 300px; margin-top: 30px; background: #ededed; padding: 30px; font-size: 20px;}

    <div class="container">
    <div class="wrapper clearfix">
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class="blk content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class=" content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class="blk content"> </div>
        </div>
        <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
            <div class=" content"> </div>
        </div>
    </div>
</div>

调用插件

$(function() {
    $('.blk').scroll({
        lastAnimation   : 0,
        quietPeriod     : 500,
        animationTime   : 800,
        ScrollUp : function() {
            $(this).css('background', 'red');
        },
        ScrollDown : function() {
            alert('Scroll Down');
        }
    });
});
我插件

(function($) {
$.fn.scroll = function( options ) {
    var settings = $.extend({
        // selector         : $(this),
        lastAnimation    : null,
        quietPeriod      : null,
        animationTime    : null,
        ScrollUp         : null,
        ScrollDown       : null
    }, options);
    return this.each( function() {
        var lastAnimation = settings.lastAnimation;
        var quietPeriod = settings.quietPeriod;
        var animationTime = settings.animationTime;
        function init(event, delta) {
            deltaOfInterest = delta;
            var timeNow = new Date().getTime();
            if( timeNow - lastAnimation < quietPeriod + animationTime ) {
                event.preventDefault();
                return;
            }
            if ( deltaOfInterest < 0 ) {
                // Call Back
                if ( $.isFunction( settings.ScrollUp ) ) {
                    settings.ScrollUp.call(this);
                }
            } else {
                // Call Back
                if ( $.isFunction( settings.ScrollDown ) ) {
                    settings.ScrollDown.call(this);
                }
            }
            lastAnimation = timeNow;
        }
        $(this).bind('mousewheel DOMMouseScroll', function(event) {
            event.preventDefault();
            var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail;
            init(event, delta);
        });
       });
       }
      }(jQuery));

这是因为这里的settings.ScrollUp.call(this); this不是指它的内部函数,所以this变成了init内部函数中的其他东西,试试这个:-

  return this.each( function() {
     var $this=this; // create variable here 
      .....
      .....
     settings.ScrollUp.call($this); //use it here like this  in init function
演示

看看是否有帮助。

我使用jQuery .hover()来存储鼠标所在的div。
然后使用变量(var hoverDiv)而不是"this"

<style>
  body {background: #2A2B30;}
  .wrapper {margin-top: 100px;}
  .wrapper div.content {border-radius: 7px; border: 1px solid #000; min-height: 120px; margin-top: 30px; background: #ededed; padding: 30px; font-size: 20px;}
</style>
  <div class="container">
  <div class="wrapper clearfix">
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class="blk content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class=" content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class="blk content"> </div>
    </div>
    <div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 content-wrapper">
      <div class=" content"> </div>
    </div>
  </div>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
/*
@see http://stackoverflow.com/questions/31340479/jquery-plugin-callback-this-cant-return-element
*/
(function($) {
  $.fn.scroll = function( options ) {
    var settings = $.extend({
      // selector     : $(this),
      lastAnimation  : null,
      quietPeriod    : null,
      animationTime  : null,
      ScrollUp     : null,
      ScrollDown     : null
    }, options);
    return this.each(function() {
      var lastAnimation = settings.lastAnimation;
      var quietPeriod = settings.quietPeriod;
      var animationTime = settings.animationTime;
      function init(event, delta) {
        deltaOfInterest = delta;
        var timeNow = new Date().getTime();
        if( timeNow - lastAnimation < quietPeriod + animationTime ) {
          event.preventDefault();
          return;
        }
        if ( deltaOfInterest < 0 ) {
          // Call Back
          if ( $.isFunction( settings.ScrollUp ) ) {
            settings.ScrollUp.call(this);
          }
        } else {
          // Call Back
          if ( $.isFunction( settings.ScrollDown ) ) {
            settings.ScrollDown.call(this);
          }
        }
        lastAnimation = timeNow;
      }
      $(this).bind('mousewheel DOMMouseScroll', function(event) {
        event.preventDefault();
        var delta = event.originalEvent.wheelDelta || -event.originalEvent.detail;
        init(event, delta);
      });
    });
  }
}(jQuery));
$(function() {
  var hoverDiv = null;
  $('.blk').hover(function(e) {
      hoverDiv = $(this);
    }, 
    function(e) {
      hoverDiv = null;
    }
  );
  $('.blk').scroll({
    lastAnimation   : 0,
    quietPeriod   : 500,
    animationTime   : 800,
    ScrollUp : function() {
      if(hoverDiv) {
        hoverDiv.css('background', 'red');
      }
    },
    ScrollDown : function() {
      if(hoverDiv) {
        hoverDiv.css('background', 'blue');
      }
    }
  });
});
</script>