繁体   English   中英

带有setInterval的jQuery插件范围

[英]jQuery Plugin Scope with setInterval

我正在努力在jQuery中编写自定义倒数计时器,我正在尝试将其编写为插件。 我根据http://jqueryboilerplate.com/https://github.com/zenorocha/jquery-plugin-patterns/的代码编写了插件,但我遇到了范围问题。

这是我的倒计时代码:

;(function ( $, window, document, undefined ) {
var pluginName = "countdown",
    defaults = {
        year: "",
        month: "",
        day: "",
        labels: true,
        includeMS: true
    },
    times = {
        ms: 0,
        sec: 0,
        min: 0,
        hr: 0,
        day: 0
    };

function Countdown( element, options ) {
    this.element = element;

    this.options = $.extend( {}, defaults, options );

    this._defaults = defaults;
    this._name = pluginName;

    this._times = times; // I wonder if this will cause multiple timers to fail.

    this.init();
}

Countdown.prototype = {

    init: function() {
        $container = $(document.createElement('div')).addClass('rd_countdown_container').append(
            $('<span class="days countdown_time"></span> <span class="day_label countdown_label">Days</span> <span class="hours countdown_time"></span> <span class="hour_label countdown_label">Hours</span><span class="minutes countdown_time"></span> <span class="minute_label countdown_label">Minutes</span><span class="seconds countdown_time"></span> <span class="second_label countdown_label">Seconds</span><span class="ms countdown_time"></span> <span class="ms_label countdown_label">ms</span>')
            );
        if(this.options.labels === false) { $container.children('.countdown_label').hide(); }
        if(this.options.includeMS === false) { $container.children('.ms, .ms_label').hide(); }
        $(this.element).html($container);
        this.options.endDate = new Date(this.options.year, this.options.month - 1, this.options.day);
        this.intervalTimer = setInterval(this._updateCountdown, 88);
    },

    _updateCountdown: function(e) {
        var x = 0;
        var ms = this.options.endDate - new Date();
        x = this._times.ms / 1000;
        var sec = Math.floor(x % 60);
        x = x / 60;
        var min = Math.floor(x % 60);
        x = x / 60;
        var hr = Math.floor(x % 24);
        var day = Math.floor(x / 24);

        $('.rd_countdown_container .days').text(day);
        $('.rd_countdown_container .hours').text(hr);
        $('.rd_countdown_container .minutes').text(min);
        $('.rd_countdown_container .seconds').text(sec);
        $('.rd_countdown_container .ms').text(this._pad(ms % 1000, 3));
    },

    _pad: function(num, size) {
      var s = "000000000" + num;
      return s.substr(s.length-size);
    },

    stop: function() {
        console.log("Testing stop");
        clearInterval(this.intervalTimer);
    }
};

$.fn[pluginName] = function ( options ) {
    var args = arguments;
    if (options === undefined || typeof options === 'object') {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, new Countdown( this, options ));
            }
        });
    } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
        return this.each(function () {
            var instance = $.data(this, 'plugin_' + pluginName);
            if (instance instanceof Plugin && typeof instance[options] === 'function') {
                instance[options].apply( instance, Array.prototype.slice.call( args, 1 ) );
            }
        });
    }
};
})( jQuery, window, document );

如果我正确理解样板文件,则所有插件设置都存储在页面上DOM中实例化的对象中。

我遇到的问题是setInterval中调用的函数无法访问插件对象的其余部分,因此它实际上无法使endDate计算时间差。 此外,当我调用$('.countdown').countdown('stop') ,它不会清除setInterval函数。

那么,jQuery插件中是否存在一种我缺失的模式或只是忽略了一些非常基本的模式? 此外,任何有关提高性能的建议都将受到赞赏。 谢谢!

当setInterval调用_updateCountdown ,范围是window ,而不是倒计时插件的实例。 为了让_updateCountdown能够访问插件的其余部分,您需要像这样代理调用:

setInterval($.proxy(this._updateCountdown, this), 88);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM