挖空映射对象未由杜兰达尔视图模型返回

Knockout Mapping Object Not Returned by Durandal Viewmodel

本文关键字:视图 模型 返回 杜兰达 映射 对象      更新时间:2023-09-26

我计划使用挖空映射插件将ajax调用返回的数据映射到Durandal框架下的视图模型。但是,我不知道如何返回映射的对象,以便视图可以使用它。这是我用于视图模型登录的代码.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,我将其返回到视图中。但是,当我检查 Web 检查器下的"viewmodels/login"返回的 loginInterfaceData 对象时,它是一个空对象。我能想到的唯一理由是视图模型在映射完成之前返回loginInterfaceData。但是,我不知道如何防止这种情况发生。

任何想法/建议将不胜感激。提前感谢!

发生这种情况是因为您返回了对内部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

显然,问题在于在调用activate函数之前返回loginInterfaceData对象,导致视图接收原始空对象。我的解决方案最终是首先将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

希望这可以帮助遇到与我相同问题的人。干杯。