【问题标题】:Extending knockout.js mapping with moment.js support使用 moment.js 支持扩展 knockout.js 映射
【发布时间】:2013-12-05 22:56:56
【问题描述】:

是否有可能扩展淘汰映射插件以在取消映射时处理不同类型的映射?

我有这个模型:

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

    self.requestFrom = ko.observable(moment().subtract("days", 1));
    self.requestTo = ko.observable(moment());
    // additional properties.
};

为了得到一个普通的 JavaScript 对象,我正在这样做:

var model = new Model();
var obj = mapping.toJS(model, {
    "ignore": ["requestFrom", "requestTo"]
});
obj.requestFrom = model().requestFrom().toISOString();
obj.requestTo = model().requestTo().toISOString();

我想避免手动处理矩对象的转换,而是为敲除映射编写一些扩展,它知道如何处理矩类型的对象,并将它们作为它们的 ISO 字符串表示形式返回。

有什么想法吗?

【问题讨论】:

  • 我知道这不是您想要的,但您可以使用带有 moment.js 的 Knockout 绑定处理程序来操作日期和时间
  • 在这种情况下,这是因为我需要先将其转换为纯 JS 对象,然后才能在 AJAX 请求中使用它。
  • 如果您使用绑定处理程序,那么您的可观察日期/时间的底层格式不会改变——唯一改变的是用户看到的内容。因此,每当需要回发到服务器时,您都可以执行ko.toJS(model)ko.toJSON(model) 并将该数据发回。您的服务器将以与您检索它们相同的格式接收日期/时间

标签: javascript knockout.js knockout-mapping-plugin momentjs


【解决方案1】:

当您将对象作为 Ajax 参数传递时,通常会在您的对象上自动调用 toJSON()

这可能不是您正在寻找的直接答案,但我认为在您的模型上添加自定义 toJSON() 效果很好。您可以非常精确地控制要发送的数据部分和格式。

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

    self.requestFrom = ko.observable(moment().subtract("days", 1));
    self.requestTo = ko.observable(moment());

    // additional properties.

    self.toJSON = function()
    {
        return { 
            requestFrom: self.requestFrom(), 
            requestTo: self.RequestTo(),
            otherProperty: self.otherProperty()
        }
    }
};

您可以直接在 Ajax 请求中使用它,而无需手动转换。

var model = new Model();

$.ajax({
    url: '/test/PersonSubmit',
    type: 'post',
    dataType: 'json',
    data: model
});

请注意,moment() 的默认 toJSON() 实现已经是 toISOString()。查看moment.js的源码:

// add aliased format methods
moment.fn.toJSON = moment.fn.toISOString;

【讨论】:

  • 感谢 Dirk,我认为这是一个更好的解决方案。关于您对 toJSON 的时刻实现的评论,这是否意味着如果我做了 ko.toJS(model),它应该给我一个对象,其中 requestFrom/To 是 ISO 字符串?这样做,我收到一个错误:“TypeError:this.clone is not a function.moment:1711 return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [格林威治标准时间]ZZ");"有什么想法吗?
  • 对不起,没有给我敲钟!如果你有小提琴我可以看看。如果您采用这种方法,我想知道您是否真的需要 ko.toJS,因为您可以将模型直接传递给 $.ajax 或 $.post,它会在每个对象上自动为您调用 toJSON。
  • 问题是我正在使用 Knockout,所以在不调用 toJS 的情况下传递对象,只会序列化敲除 observables。我会考虑创建一个 Fiddle 示例,希望明天。
  • 正如您在示例中看到的,我在 toJSON() 方法中手动解开 ViewModel 中的 observables。这样,您始终可以完全控制您发送的内容,并且不需要 toJS:每个 viewModel 都有责任返回自己在 toJSON 方法中解包的数据。请注意,子 ViewModels 的 toJSON 也被调用,因此这适用于复杂的层次结构。
  • 啊,我看到了德克。我现在实际上正在使用这种方法。我刚刚了解到我可以在不实现自己的 toJSON 方法的情况下使用淘汰赛中的 toJS 方法。但这是有道理的,我会坚持这种方法,因为正如你所说,我可以完全控制数据的展开方式。再次感谢您。
【解决方案2】:

您是否考虑过使用原型来扩展ko 对象?我会将observable 方法克隆到一个新的momentObservable 方法中,然后可以这样调用:

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

  self.requestFrom = ko.momentObservable.subtract("days", 1));
  //other operations

};

【讨论】:

  • 感谢您回答布赖恩。不过我更喜欢 Dirks 解决方案 :-)
  • 当然!它相当优雅并且具有性能优势!如果您的应用程序使用大量moment,我想我会提供这种替代方案,(或者如果未来的 SO 用户有类似的问题与该特殊区别。)快乐黑客!感谢投票!
猜你喜欢
  • 2019-04-28
  • 1970-01-01
  • 2012-09-21
  • 2014-06-12
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2013-12-26
  • 1970-01-01
相关资源
最近更新 更多