【问题标题】:properly accessing an instance out of scope and templating for mutiple instances正确访问超出范围的实例并为多个实例进行模板化
【发布时间】:2015-12-13 02:44:27
【问题描述】:

我在我的 jsfiddle (http://jsfiddle.net/cjros/2xuxb2kp/) 上做了一些笔记,到目前为止,您可以看到,我有一个带有几个方法的 Timer 模型。

var TimerModel = function (timerName, startTimerLimit) {

this._init = function () {
    this.setTimerName(timerName);
    this.startTimerLimit = startTimerLimit * 1000; // in milliseconds
    this.setInitialTimerDisplay(startTimerLimit);
    this.isTimerActive = false;
};

this.setTimerName = function (timerName) {
    $('#display-timer-name').html(timerName);
};

this.setInitialTimerDisplay = function (timerLimit) {
    $('#display-timer-limit').html(timerLimit);
};

this.startTimer = function () {
    this.isTimerActive = true;
    var startingCountdown = setInterval(function () {
        if (this.startTimerLimit === 0 && this.isTimerActive) {
            clearInterval(startingCountdown);
            this.isTimerActive = false;
            alert('Time is up!');
        } else {
         this.startTimerLimit -= 1000;
         $('#display-timer-limit').html(this.startTimerLimit / 1000);
        }
    }.bind(this), 1000);
};

this.pauseTimer = function () {
    if (this.isTimeActive) { 
        clearInterval(/* how would i access this.startTimer()'s setInterval? */) 
    };
};

this._init(); 

}

$('#start-timer').click(function () {
    var timerName = $('#set-timer-name').val();
    var initTime = parseInt($('#set-timer-limit').val());
    var timer = new TimerModel(timerName, initTime);
    timer.startTimer();
});

$('#pause-timer').click(function() {
    // how would I properly access my 'timer' instance that I created in the '#start-timer' action event?
});
  • 我想知道如何访问我在开始按钮单击事件中创建的实例(第 48 行)。如果您在我的暂停按钮单击事件上看起来有点低,我正在尝试弄清楚如何访问同一个实例,但不一定知道如何做到这一点。

  • 我的另一个问题是关于尝试访问或与 Timer 模型中的另一种方法“通信”。正如您在第 39 行看到的那样,我正在尝试从 this.startTimer 方法中清除Interval,但并不真正知道如何访问该函数/变量。

  • 关于 javascript 知识的更广泛说明,我的代码的这种格式是否是创建模型(类)的正确方法?是否有人有任何其他建议我应该阅读或查看格式化我的代码以使其更容易并避免我上面遇到的一些问题?

    • 我想知道的另一个重要问题是:如果我想创建多个此计时器模型的实例,以便可以单独启动/停止/暂停每个实例,该怎么办?我现在应该如何考虑格式化此代码?我是否需要一个超类或其他东西来监视所有这些实例?这是模板的用武之地吗(绝对不能有多个相同的 DOM 元素 id)?我知道如何通过创建视图模型并将它们模板化来实现淘汰赛;我只是想更好地了解如何在本地执行此操作(jQuery 被用作例外)。

非常感谢您提前提供的帮助。有很多东西要学!

【问题讨论】:

  • 你真的应该把 JSFiddle 代码带入这个问题。链接可能会被破坏,并且由于您引用了问题中的代码,因此它需要在此处可用。
  • @jwatts1980 感谢您的提醒!

标签: javascript scope templating


【解决方案1】:

看起来您可能需要深入研究 JavaScript 范围。只要函数存在,在函数访问范围内创建的对象/变量将保持在范围内。例如,如果您在TimerModel 的主体中创建区间变量,则可以在整个函数中使用。

var TimerModel = function (timerName, startTimerLimit) {
    var startingCountdown = null;

    this.startTimer = function () {
        this.isTimerActive = true;
        startingCountdown = setInterval(
        //......
    };

    //And it can be easily cancelled later
    this.cancelTimer = function() {
        clearInterval(startingCountdown);
    };
};

所以你创建了一个变量var tm = new TimerModel("test", 20);。 只要变量tm存在,对象实例中的函数/方法就可以访问startingCountdown

关于存储对象,我要提到的一个 jQuery 小技巧是 $.data() 函数。 $.data() 是一种将任意数据存储到 DOM 元素中的方法。示例用法是:

var el = $("someSelector");
var tval = parseInt(el.val());
var tm = new TimerModel("test", tval);
el.data("timer", tm);

现在对象tm 存储在DOM 中。稍后检索它:

var tm = $("someSelector").data("timer");

或者您可以执行一些操作,例如存储计时器的名称:

el.data("timerName", "testTimer");
var timerName = el.data("timerName");

我上面提到的范围定义也适用于 jQuery。因此,在准备好的脚本中,您创建的任何变量都可以通过函数使用:

$(document).ready(function() {

    //Create a variable to hold the timer
    var timer = null;

    $('#start-timer').click(function () {
        var timerName = $('#set-timer-name').val();
        var initTime = parseInt($('#set-timer-limit').val());

        //Create the timer on the variable, or maybe see if the user wants
        // to cancel the timer if it already exists.
        if (timer) {
            if (confirm("Cancel the current timer?")) {
                timer.destroy(); //<==assumes this method is created.
                timer = null;
            } else {
                return;
            }
        }

        timer = new TimerModel(timerName, initTime);
        timer.startTimer();
    });

    $('#pause-timer').click(function() {
        if (timer) timer.pause();
    });
});

如果你想把这个想法提升一个档次,并且希望能够创建任意数量的定时器,那么你最好创建一个对象来处理定时器。您有一些计时器名称已在使用中。您可以将名称属性添加到现有的 TimerModel

var TimerModel = function (timerName, startTimerLimit) {
    this.name = timerName;
};

因此您以后可以按名称访问计时器。

var TimerModelCollection = function() {
    var timers = [];

    this.addTimer = function(name, time) {
        var tm = new TimerModel(name, time);
        timers.push(tm);
        return tm;
    };

    //Other methods to remove timers, and such, as well as a way to access
    // them by name would be needed too.
    this.getByName = function(name) {
        for(var i in timers)
            if (timers[i].name == name) 
                return timers[i];
        return null;
    };

    //etc, etc...
};

使用上面提到的其他一些方法,您也许能够弄清楚如何创建计时器、保存它们或它们的名称以供以后检索。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-03
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-04
    相关资源
    最近更新 更多