3

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 プラグインに、欠落している、または非常に基本的なものを見落としているパターンはありますか? また、パフォーマンスを向上させるための提案をいただければ幸いです。ありがとう!

4

1 に答える 1

6

setInterval が呼び出されると_updateCountdown、スコープはwindowであり、カウントダウン プラグインのインスタンスではありません。がプラグインの残りの部分にアクセスできるようにするには、次_updateCountdownのように呼び出しをプロキシする必要があります。

setInterval($.proxy(this._updateCountdown, this), 88);
于 2013-01-30T18:00:46.297 に答える