【问题标题】:Knockout js how to Implement Countdown TimerKnockout js如何实现倒数计时器
【发布时间】:2014-07-25 17:59:22
【问题描述】:

我是 Knockout js 的新手。尝试使用 Knockout js 在 html 上实现倒数计时器

为此,我在视图中添加了 4 个 html 元素(输入、跨度和开始、停止按钮)。当按下开始按钮时,写在<input>对象上的值应该被传递给refreshViewModel,并且会有倒计时过程。当倒计时正在处理时,剩余时间将显示在<span> 元素内。如果按下停止按钮,倒计时将停止。

如果倒计时完成另一个函数(从另一个 viewModel 回调),该函数正在使用某些参数过滤页面。

将文本框值绑定到跨度值。我无法弄清楚如何动态计算和显示 span 内的剩余值?

HTML:

<div id="pnlTimer" class="row">
  <div class="span2 pull-right" style="border:1px solid rgb(218, 218, 218)" >
    <span style="font-weight:bold">Reload Interval</span>
    <br />
    <input  id="initialTime" style="width:20px;height:14px" data-bind="value:  initialTime" />
    <span id="remainingTime" style="visibility:hidden"> / 15</span> second(s)
    <button class="btn" style="margin-top:5px" id="StartCounter" data-bind="click: StartCounter">
       <i class="icon-play"></i>
    </button>
    <button style="visibility:hidden;margin-top:5px;margin-left:-44px" class="btn"  id="StopCounter" data-bind="click: StopCounter">
       <i class="icon-stop"></i>
    </button>
  </div>
</div>

Js:

     @Url.Content("~/Content/App/viewModels/listCasesViewModel.js
     @Url.Content("~/Content/App/viewModels/RefreshPageTimerViewModel.js                       



$(document).ready(function () {
    var viewModel = new ListCasesViewModel();
    viewModel.init();

    var pnl = $("#pnlFilterPanel").get()[0];
    ko.applyBindings(viewModel, pnl);


    var viewModelTimer = new RefreshPageTimerViewModel();
    viewModelTimer.init();

    var pnlTimer = $("#pnlTimer").get()[0];
     ko.applyBindings(viewModelTimer, pnlTimer);

    viewModelTimer.callBackMethod = viewModel.filter;


});


第一个 viewModel :RefreshPageTimerViewModel:

var RefreshPageTimerViewModel = function () {
var self = this;


self.StartCounter = ko.observable();
self.StopCounter = ko.observable();
self.initialTime = ko.observable();
self.remainingTime = ko.computed(function () {
    return self.initialTime();
}, self);

countDown: ko.observable()


this.init = function () {
    self.Count();

}

this.callBackMethod = function () {
    alert("not implemented!");
}

this.Count = function () {

    var initial = self.initialTime; // initialTime value;
    var remaining = self.remainingTime; 


    if (remainingTime <= 0) {
        this.ExecuteCallBackMethod();
    }
}

this.ExecuteCallBackMethod = function () {
    this.callBackMethod();
}



};

第二个视图模型:ListCasesViewModel:

   var ListCasesViewModel = function () {
    var self = this;

self.selectedStartDate = ko.observable(null);
self.selectedEndDate = ko.observable(new Date());
self.selectedSearchKey = ko.observable("");
self.selectedStatuses = ko.observableArray();
self.selectedHospitals = ko.observableArray();

// methods...
this.init = function () {
    self.selectedEndDate(new Date());
    self.filter();
}

this.filter = function () {

    // get filter control values
    var startDate = self.selectedStartDate(); // dtStart.value();
    var endDate = self.selectedEndDate(); //dtEnd.value();
    var searchText = self.selectedSearchKey();

    //And Some calculations....

【问题讨论】:

    标签: javascript jquery html knockout.js


    【解决方案1】:

    主要问题是您的 ViewModel 代码,它使用 observable 您想要一个函数(启动和停止计数器)。此外,它似乎没有明确定义它要做什么。

    另外,我假设您希望“开始”按钮在计时器停止时显示,而“停止”按钮在计时器开始时显示 - 所以我也冒昧地添加了此功能。

    这是重写后的视图模型:

    var RefreshPageTimerViewModel = function () {
        var self = this;
    
        self.timerId = 0;
        self.elapsedTime = ko.observable(0);
        self.initialTime = ko.observable(0);
        self.remainingTime = ko.computed(function(){
            return self.initialTime() - self.elapsedTime();
        });
        self.isRunning = ko.observable(false);
    
        self.StartCounter = function(){
            self.elapsedTime(0);
            self.isRunning(true);
            self.timerId = window.setInterval(function(){
                self.elapsedTime(self.elapsedTime()+1);
                if(self.remainingTime() == 0){
                    clearInterval(self.timerId);
                    self.isRunning(false);
                    self.Callback();
                }
            },1000)
        }
        self.StopCounter = function(){
            clearInterval(self.timerId);
            self.isRunning(false);
        }
        self.Callback = function(){}
    }
    

    需要注意的几点:

    • 有一个属性timerId,它不需要是可观察的,但允许我们停止用于增加elapsedTime的计时器

    • 有一个可观察的属性isRunning 用于控制开始和停止按钮的可见性

    • 有一个空函数Callback,可以在倒计时归零时执行任何函数。

    这是新的标记:

    <div id="pnlTimer" class="row">
      <div class="span2 pull-right" style="border:1px solid rgb(218, 218, 218)" >
        <span style="font-weight:bold">Reload Interval</span>
        <br />
        <input  id="initialTime" style="width:20px;height:14px" data-bind="value:  initialTime" />
        <span id="remainingTime" data-bind="text: remainingTime"></span> second(s)
        <button class="btn" style="margin-top:5px" id="StartCounter" data-bind="click: StartCounter, visible: !isRunning()">
           start
        </button>
        <button style="margin-top:5px" class="btn"  id="StopCounter" data-bind="click: StopCounter, visible:isRunning()">
           Stop 
        </button>
      </div>
    </div>
    

    注意visible: !isRunning() 添加到开始按钮和visible:isRunning() 到停止按钮。

    最后,这里是初始化代码:

    $(function(){
         var viewModelTimer = new RefreshPageTimerViewModel();
        viewModelTimer.Callback = function(){
            alert("finished");
        };
        ko.applyBindings(viewModelTimer);
    })
    

    请注意创建一个简单警报的回调函数。您的代码可以保持原样,即viewModelTimer.callBackMethod = viewModel.filter;

    最后,一个活生生的例子让你玩转:http://jsfiddle.net/eF5Ec/

    【讨论】:

    • 谢谢,这是我正在寻找的确切示例。小补充:“viewModelTimer.callBackMethod = viewModel.filter”从第二个 viewModel 到第一个 viewModel 引用“filter()”函数。
    猜你喜欢
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    相关资源
    最近更新 更多