Knockout ko.mapping.fromJSON没有更新

时间:2013-10-22 20:35:32

标签: knockout-mapping-plugin

我有一个带有嵌套属性的复杂对象,它从null变为实际填充的对象。我可以通过ko.mapping.fromJSON第一次将所有内容映射得很好。但是当一个事件导致后续映射发生时,属性变为null而其他事件获得值,映射变得疯狂:

http://jsfiddle.net/L5sgW/51

当“更新!”时单击按钮,警报('1')将触发,并显示“Test2”。但是,请单击“更新!”再次和警报('2')发射,但文本不会改变。有什么想法吗?

HTML:

<p> <span>Name:</span>
    <span data-bind="text: IntroData ? IntroData.Name : TempData.Name"></span>
    <button id="update" data-bind="click: Update">Update!</button>
</p>

javascript:

var ViewModel = function (data) {
    var me = this;
    ko.mapping.fromJS(data, {}, me);

    me.Update = function () {
        if (me.Index() == '0' || me.Index() == '2') {
            alert('1');
            ko.mapping.fromJS(stuff2, {}, me);
        } else {
            alert('2');
            ko.mapping.fromJS(stuff3, {}, me);
        }
    };

    return me;
};

var stuff = {
    Index: '0',
    IntroData: {
        Name: 'Test'
    },
    TempData: null

};

var stuff2 = {
    Index: '1',
    IntroData: {
        Name: 'Test2'
    },
    TempData: {
        Name: 'Temp2'
    }
};

var stuff3 = {
    Index: '2',
    IntroData: null,
    TempData: {
        Name: 'Temp3'
    }
};

window.viewModel = ko.mapping.fromJS(new ViewModel(stuff));
ko.applyBindings(window.viewModel);

1 个答案:

答案 0 :(得分:0)

你在东西和东西中为IntroData和TempData提供了不同的形状。

1 /当ko.mapping.fromJS解释TempData:null时,它将产生一个ko.observable(null)。 2 /当ko.mapping.fromJS解释TempData:{Name:'Temp3'}时,它将生成一个具有成员'Name'的Object,它是一个ko.observable('Temp3')。

例如,东西:

    > ko.mapping.fromJS({ Index: '0', IntroData: { Name: 'Test' }, TempData: null }, {});

    Object {Index: function, IntroData: Object, TempData: function, __ko_mapping__: Object}
      Index: function observable() {
      IntroData: Object
        Name: function observable() {
        __proto__: Object
      TempData: function observable() {
      __ko_mapping__: Object
      __proto__: Object

and stuff2:

    > ko.mapping.fromJS({ Index: '1', IntroData: { Name: 'Test2' }, TempData: { Name: 'Temp2' } }, {});

    Object {Index: function, IntroData: Object, TempData: Object, __ko_mapping__: Object}
      Index: function observable() {
      IntroData: Object
        Name: function observable() {
        __proto__: Object
      TempData: Object
        Name: function observable() {
        __proto__: Object
      __ko_mapping__: Object
      __proto__: Object

请注意,TempData是stuff的映射对象中的一个函数(可观察),但是在stuff2的映射对象中具有子属性“Name”的对象。

那为什么这不起作用?您的绑定指定:

    text: IntroData ? IntroData.Name : TempData.Name

问题是IntroData 永远不为空,并且始终是“真实的”。 (它可以是一个对象,也可以是一个可观察的。在任何一种情况下,都不是null。)那么该怎么办?好吧,我们可以使定义形状相似,以便ko.mapping正确更新值。我将你的绑定修改为:

    text: IntroData.Name() ? IntroData.Name : TempData.Name

并将您的对象定义更改为:

    var stuff = {
        Index: '0',
        IntroData: {
            Name: 'Test'
        },
        TempData: {
            Name: null
        }
    };

    var stuff2 = {
        Index: '1',
        IntroData: {
            Name: 'Test2'
        },
        TempData: {
            Name: 'Temp2'
        }
    };

    var stuff3 = {
        Index: '2',
        IntroData: {
            Name: null
        },
        TempData: {
            Name: 'Temp3'
        }
    };

您会看到更新按钮现在显示每次点击的更改。看起来你正试图循环使用东西 - &gt; stuff2 - &gt; stuff3。代码不会这样做,但你不应该发现很难做到这一点。 : - )