我接手了一个严重依赖于knockout.js数据绑定技术的项目。该应用程序的目的基本上是显示(运动)课程。必需的是课程名称和开始时的日期(和时间)。 数据通过ajax拉取,然后通过knockout.js绑定到视图
基本上,有一个模型看起来像这样:
BaseModel: function() {
var self = this;
var mappingOptions = {};
self.setMappingOptions = function (options) {
$.extend(mappingOptions, options);
};
self.map = function (data) {
ko.mapping.fromJS(data, mappingOptions, self);
return self;
};
self.isNew = function() {
return !(typeof(self.id) == 'function' && self.id() != null);
};
}
Course: function() {
BaseModel.call(this);
var self = this;
ko.mapping.fromJS({
name: null,
date: moment().tz('UTC').minute(0).second(0).format('YYYY-MM-DDTHH:mm:ssZ'),
timezone: null,
duration: null
}, {}, self);
self.duration = ko.integerObservable();
self.dateDateTime = new IMWeb.ko.DateTime(self.date);
self.timezone = self.dateDateTime.timezone();
self.dateDateTime.timezone.subscribe(function(timezone) {
self.timezone = timezone;
});
}
视图将此模型绑定为:
<input type="text" class="form-control" id="nameInput" data-bind="value: name"/>
<input type="text" class="form-control" id="dateInput" data-bind="value: clientDateDateTime.date, event:{focus: $parent.onDateInput, mouseover: $parent.onDateInput}, enable: changeable"/>
<input id="timeInput" type="text" class="form-control" data-bind="value: dateDateTime.time, event:{focus: $parent.onTimeInput, mouseover: $parent.onTimeInput}, enable: changeable">
从服务器发送的json数据中的日期设置为UTC,因此我创建了以下函数以将其转换为客户端的时区:
/**
* Converts the given UTC date to local date of the client by subtracting
* the local timezone offset from the given date.
*
* @param {Date} utcDate The date object to convert
* @returns {Date} The converted date object
*/
var UTC2LocalDate = function (utcDate) {
var timestamp = utcDate.getTime(); // Number of miliseconds since Jan 1st 1970, 0:00:00 UTC
var offset = (new Date()).getTimezoneOffset(); // Local client offset in minutes
timestamp -= offset * 60 * 1000; // Fix date with offset by converting offset minutes to miliseconds
return new Date(timestamp);
};
现在,这是一个棘手的部分:我如何运行这个&#34;转换代码&#34;没有干扰数据绑定机制?
基本上,我希望这种行为发生:
模型更改 - &gt;模型中的日期将使用UTC2LocalDate()
转换为客户的本地时区,并且视图会更新(不更改模型的原始UTC值)。
用户更改<input>
中的值 - &gt;日期/时间转换为UTC并保存到模型。
答案 0 :(得分:1)
来回转换最好由writable computed处理。您将拥有UTC日期的普通可观察量,以及基于它计算的可写值。基本结构如下:
vm.utcDate = ko.observable();
vm.localDate = ko.computed({
deferEvaluation: true,
read: function () {
return toLocalDate(vm.utcDate());
},
write: function (newLocalDate) {
vm.utcDate(toUtcDate(newLocalDate));
}
});
(我显然已将toLocalDate
和toUtcDate
的实现留给您了。)在要显示的任何绑定中使用localDate
变量和/或接受本地日期。它会在utcDate
更新后自动更改,并会在输入新的utcDate
值时自动更改localDate
。
答案 1 :(得分:0)
我的方法是在用于构造dateDateTime之前使用UTC2LocalDate转换self.date的值。此时,您的用户将与本地日期时间进行交互。
接下来,你可以编写一个转换回来的函数,让我们称之为Local2UtcDate,并通过订阅self.dateDateTime来更新你的self.date值。它看起来像这样:
self.duration = ko.integerObservable();
self.dateDateTime = new IMWeb.ko.DateTime(UTC2LocalDate(self.date));
self.timezone = self.dateDateTime.timezone();
self.dateDateTime.timezone.subscribe(function(timezone) {
self.timezone = timezone;
});
self.dateDateTime.subscribe(function(changedLocalDate){
self.date(Local2UtcDate(changedLocalDate));
});
我不确定服务器预计会回发什么,但这样self.dateDateTime将是本地时间,self.date将是更新的UTC时间。