如何处理循环中的时刻日期?

How to deal with moment dates in a loop?

我很难解决这个问题。我想根据指定的时间段获取两个日期的差异。

我有下面的代码片段。每当我单击按钮时,它应该用差异填充数组(基于指定的时间段)。

但是,目前正在发生的事情是,一旦我单击该按钮,它就会填充相同的日期。有什么想法吗?

var fooObj = function(){
    var self = this;
    self.month = ko.observable();
    self.formatted = ko.computed(function() {
        return month().format('ddd, DD MMM YYYY');
    });
};

var vm = (function() {
    var startDate = ko.observable(moment([2015, 10, 1])),
        startDateFormat = ko.computed(function() {
            return startDate().format('ddd, DD MMM YYYY');
        }),
  endDate = ko.observable(startDate().add(5, 'days')),
        endDateFormat = ko.computed(function() {
            return endDate().format('ddd, DD MMM YYYY');
        }),
        dateDiff = endDate().diff(startDate(), 'days'),
        foo = ko.observableArray(),
        test = function(){
            for(var i = 0; i<=5; i++){
                foo.push(startDate().add(1, 'days'));
            }
        };
    
    return {
        startDate: startDate,
        endDate: endDate,
        foo: foo,
        test: test,
        dateDiff: dateDiff,
        startDateFormat: startDateFormat,
        endDateFormat: endDateFormat
    };
}());

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre><br />
<button data-bind="click: $root.test">Click me for test</button>

看来您陷入了一个微妙的语法陷阱,这是一个很容易犯的错误。 moment.js 提供了方法链接语法,它提供了您的案例中混淆的根源。

例如,当您以这种方式为 endDate 设置默认值时,基于 startDate:

endDate = ko.observable(startDate().add(5, 'days'))

您没有得到预期的结果,因为方法链接为您提供了原始值,然后将其增加了 5 天。

相反,如果您克隆 moment 对象然后添加,您将得到我相信您期望的结果:

endDate = ko.observable(moment(startDate()).add(5, 'days'))

并且您还需要在 test 方法的循环内执行相同的操作:

foo.push(moment(startDate()).add(i, 'days')); // use index var i for number of days

完整的可运行示例在这里:

var vm = (function() {
    var startDate = ko.observable(moment([2015, 10, 1])),
        startDateFormat = ko.computed(function() {
            return startDate().format('ddd, DD MMM YYYY');
        }),
        // make sure to clone startDate before add
 endDate = ko.observable(moment(startDate()).add(5, 'days')),
        endDateFormat = ko.computed(function() {
            return endDate().format('ddd, DD MMM YYYY');
        }),
        dateDiff = endDate().diff(startDate(), 'days'),
        foo = ko.observableArray(),
        test = function(){
            for(var i = 0; i<=5; i++){
                // make sure to clone startDate before adding days
                foo.push(moment(startDate()).add(i, 'days'));  // use index var i for number of days
            }
        };
    
    return {
        startDate: startDate,
        endDate: endDate,
        foo: foo,
        test: test,
        dateDiff: dateDiff,
        startDateFormat: startDateFormat,
        endDateFormat: endDateFormat
    };
}());

ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<pre data-bind="text: ko.toJSON($root, null, 2)"></pre><br />
<button data-bind="click: $root.test">Click me for test</button>