【问题标题】:Set nested mapped observable object back to null?将嵌套映射的可观察对象设置回 null?
【发布时间】:2015-11-22 13:48:33
【问题描述】:

我在使用映射插件映射的 ajax 调用中有 3 个对象

  • 可观察的表数组
  • 每张桌子都有一个可观察的座位数组
  • 每个座位可能有也可能没有玩家(可空属性)

我这样映射(使用非常简化的代码示例),大部分繁重的工作由插件完成,然后是一些计算

var TableViewModel = function (data) {
   var self = this;
   ko.mapping.fromJS(data, codeMapping, self);
}

var SeatViewModel = function (data) {
    var self = this;
    ko.mapping.fromJS(data, codeMapping, self);    

    self.CssClass = ko.computed(function () {       
        if (ko.toJS(self.Player) != null)
           return "occupiedSeat";        
        return "";
   });
}

var PlayerViewModel = function (data) {
   var self = this;
   ko.mapping.fromJS(data, codeMapping, self);    
}

var codeMapping = {
   create: function (options) {
      return new ViewModel(options.data);
   }    
   'Players': {
      create: function (options) {
           return new PlayerViewModel(options.data);
       }
   },
   'Tables': {
       create: function (options) {
           return new TableViewModel(options.data);
       }
   }
   'Seats': {
       create: function (options) {
           return new SeatViewModel(options.data);
      }
   }
}

而 ajax 看起来像这样

[{"TableId":1,"Seats":[{"SeatId":1,"Player":{"PlayerId":1}},{"SeatId":2,"Player":{"PlayerId":2}},{"SeatId":3,"Player":null}]}]

如果我决定移动玩家,比如从座位 2 移动到座位 3,我会在 UI 元素中添加点击功能

<div data-bind="foreach: Seats">
   <div class="seat" data-bind="attr: { class: CssClass() }, click:MovePlayer">                                                              
   </div>
</div>

function MovePlayerToSeat() { 
   var oldSeat = this;
   var newSeat = someArrayFirstLookupMethod();
   $.post({"/api/movePlayer"})
    .done(function (playerObj) {
       newSeat.Player = ko.observable(new PlayerViewModel(playerObj));
       oldSeat.Player = ?????
   }

}

我可以很容易地设置新对象,但是(我已经为此搜索了高低,并认为这可能是不可能的?)我无法将现有的 observable Player 重新设置为 null,因此它计算的 SeatViewModel 中的条件失败

if (ko.toJS(self.Player) != null)

我试过了

oldSeat.Player = null
//and
oldSeat.Player(null)

但第一个不起作用,第二个(正确)例外,即 Player 不是函数。

这在 Knockout 中可行吗?

编辑:

添加额外的上下文来回答下面的问题

这可能不符合,因为在尝试削减我的代码时,我可能歪曲了问题。但这不起作用,至少对于我要问的问题不起作用。

如果我手动进行映射,设置每个

self.attribute = ko.observable(data.attribute) 

最初加载数据时,这会为 null 值创建与我刚刚调用时不同的最终结果

ko.mapping.fromJS(data, {}, self).

对于前者,如果我做一个

console.log(ko.toJS(self.Player()))

吐出来

{Object {PlayerId: 1, __ko_mapping__: Object}, Object {PlayerId: 2, __ko_mapping__: Object}, Object{}}

但是,对于后者,

如果我尝试打电话

console.log(ko.toJS(self.Player()))

它会告诉我 Uncaught TypeError: self.Player is not a function。相反,我必须打电话

console.log(ko.toJS(self.Player))

因为映射直到需要时才使对象成为可观察对象,所以它保持为空。所以这产生了

{Object {PlayerId: 1, __ko_mapping__: Object}, Object {PlayerId: 2, __ko_mapping__: Object}, null} 

因此,以您提到的方式将其设置为 null 是行不通的,因为映射不会使嵌套对象以相同的方式发挥作用(我不知道这是错误还是设计使然?)。

这项调查向我强调了通过手动处理此对象映射可能有一种解决方法,但我想我的问题仍然是,是否可以取消映射/取消设置可观察对象,使其仅作为属性名称存在,但是不再作为可观察对象?

【问题讨论】:

    标签: knockout.js knockout-mapping-plugin


    【解决方案1】:

    第二种是取消设置 oldSeat Player 的适当方法。因为ko.observable 对象实际上是函数。

    oldSeat.Player(null);
    

    Reading and writing observables.

    【讨论】:

    • 我在我的问题中添加了额外的上下文来解决您的回复
    猜你喜欢
    • 2021-09-22
    • 1970-01-01
    • 2014-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多