jquery - $(this) 在自定义 jQuery 函数中不起作用

标签 jquery momentjs

我使用 moment.js 和 moment-duration-format plugin 制作了一个 jQuery 倒计时器。 .

请注意,$('div#countdown') 是硬编码在函数内部的。该函数的工作方式如此处所示。但如果我更改对 $(this) 的硬编码引用,它就不起作用。 console.log($this) 返回一个空对象。

我尝试在函数开始时将 $(this) 设置为变量,以防间隔造成范围问题,但这没有什么区别。

令人困惑的部分是,我之前已经在自定义 jQuery 函数中使用过这种精确的 $.fn.xxx = function 语法,并且 $(this) 在这些函数中工作得很好。这个特定函数的一些问题导致了它的失败。

<script>
    $.fn.countdown = function ( seconds, tFormat, stopAtZero ) {
        tFormat = (typeof tFormat !== 'undefined') ? tFormat : 'hh:mm:ss';
        stopAtZero = (typeof stopAtZero !== 'undefined') ? stopAtZero : true;
        var eventTime = Date.now() + ( seconds * 1000 );
        var diffTime = eventTime - Date.now();
        var duration = moment.duration( diffTime, 'milliseconds' );
        var interval = 0;
        var counter = setInterval(function () {
            $('div#countdown').text( moment.duration( duration.asSeconds() - ++interval, 'seconds' ).format( tFormat, { trim: false }) );
            if( stopAtZero && interval >= seconds ) clearInterval( counter );
        }, 1000);
    };

    $('div#countdown').countdown( 30*60, 'mm:ss' );
</script>

<div id="countdown"></div>

编辑:已解决。功能很好。它只需要位于 Div 之后(或文档加载之后)::headdesk::

最佳答案

问题是因为 setTimeout() 中的函数在与外部函数不同的范围内运行。因此 this 并不是您所期望的那样。您需要缓存 this 引用。

另请注意,您可以通过向包含选项的函数提供一个对象来稍微改进逻辑。然后您可以使用 $.extend 提供默认值。您还应该循环 this 以使用户能够提供对象集合来初始化插件。试试这个:

$.fn.countdown = function(options) {
  var defaults = {
    seconds: 0,
    tFormat: 'hh:mm:ss',
    stopAtZero: true,
    complete: function() {}
  };
  var settings = $.extend(defaults, options);

  $(this).each(function() {
    var $el = $(this);
    var eventTime = Date.now() + (settings.seconds * 1000);
    var diffTime = eventTime - Date.now();
    var duration = moment.duration(diffTime, 'milliseconds');
    var interval = 0;
    var counter = setInterval(function() {
      $el.text(moment.duration(duration.asSeconds() - ++interval, 'seconds').format(settings.tFormat, {
        trim: false
      }));
      if (settings.stopAtZero && interval >= settings.seconds) {
        clearInterval(counter);
        settings.complete();
      }
    }, 1000);
  });
}

$('div').countdown({
  seconds: 10,
  complete: function() {
    console.log('finished!');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/1.3.0/moment-duration-format.min.js"></script>
<div></div>

关于jquery - $(this) 在自定义 jQuery 函数中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43683505/

相关文章:

javascript - 滚动播放一次视频有问题吗?

javascript - 产品过滤 PHP

javascript - 我如何使用 JQuery WHEN 和 THEN 同步两个 Backbone 提取调用

javascript - Moment.js - 如何获得日期后的年数,而不是四舍五入?

javascript - 如何使用 Moment 解析没有偏移的时间字符串?

node.js - 时刻和时区转换本地时间失败

javascript - BX slider 可通过“阅读更多”按钮调整自适应高度

jquery - 如何将 ASP.NET MVC 3 View 显示为弹出窗口

javascript - 从日期中减去时间 - 时刻 js

javascript - 如何用 moment.js 减去 2 次,然后减去一些分钟