Durandal Viewmodel不返回Knockout Mapping对象

时间:2015-01-30 07:17:49

标签: javascript mvvm knockout.js durandal

我打算使用Knockout Mapping插件将从ajax调用返回的数据映射到Durandal框架下的viewmodel。但是,我不知道如何返回映射对象,以便视图可以使用它。这是我的viewmodel login.js代码:

define(function (require) {
    var system = require('durandal/system'),
          app = require('durandal/app'),
          ko = require('knockout'),
          komapping = require('komapping'),
          deferred = $.Deferred(),
          loginOptionsUrl = '/json/loginOptions.json',
          loginInterfaceData = {};

ko.mapping = komapping;

return {

activate: function(){
     var request = $.getJSON(loginOptionsUrl)
          .done(function(data){
          loginInterfaceData = ko.mapping.fromJS(data);
          system.log(loginInterfaceData); //Do a check here; loginInterfaceData contains all the right data
          deferred.resolve();  
          });
     return deferred.promise();
},
loginInterfaceData: loginInterfaceData; //However, the view gets an empty object

如您所见,从ko.mapping返回的对象被分配给loginInterfaceData,我将返回到视图。但是,当我检查' viewmodels / login'返回的loginInterfaceData对象时在Web Inspector下,它是一个空对象。我能想到的唯一原因是viewmodel在映射完成之前返回loginInterfaceData。但是,我不知道如何防止这种情况发生。

任何想法/建议都将受到最高的赞赏。提前致谢!

2 个答案:

答案 0 :(得分:0)

这是因为您返回对内部loginInterfaceData的引用,但在您的activate函数中重新分配该变量,因此之前返回的loginInterfaceData始终是一个空对象。您可以做的是为loginInterfaceData返回一个getter函数,如下所示:

...
getLoginInterfaceData: function() {
  return loginInterfaceData;
}
...

在您的通话代码中,activate完成后,只需拨打getLoginInterfaceData() 这是一个简单的例子:



function foo() {
    var bar = {};
    return {
        setBar : function(x) {
            bar = x;
        },
        bar: bar,
        getBar: function() {
            return bar;
        }
    }
}

var f = foo();
f.setBar(5);
console.log(f.bar); // logs empty object
console.log(f.getBar()); // logs value of inner foo.bar




答案 1 :(得分:0)

显然问题在于在调用loginInterfaceData函数之前返回activate对象,导致视图接收原始的空对象。我的解决方案最终是首先将loginInterfaceData绑定到空数据,然后在通过Ajax接收数据后更新它。像这样:

(...)    

ko.mapping = komapping;
loginInterfaceData = ko.mapping.fromJS({}); //instead of assigning loginInterfaceData = {}, I use KO Mapping with an ampty JSON object

(...)

return {

activate: function(){
            return $.ajax({
                url: loginOptionsUrl,
                contentType: 'application/json',
            }).done(function(data) {
                ko.mapping.fromJS(data, loginInterfaceData);//so here, instead of mapping for the first time, I remap/update it
            });

},
loginInterfaceData: loginInterfaceData; //at this point, loginInterfaceData is still empty object but will be updated/remap once ajax call is successful

希望这可以帮助遇到与我相同问题的人。欢呼声。