【发布时间】: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