通过映射插件重新映射对象后,属性的可观察订阅者停止工作
Observable subscriber of properties stop working after remapping object by mapping plugin
ViewModel 从 JSON 初始化并映射到 $(document).ready(..)
$(document).ready(function ()
{
viewmodel = new Order();
var data = { json data };
ko.mapping.fromJSON(data, {}, viewmodel);
ko.applyBindings(viewmodel);
});
class Order
{
ID: KnockoutObservable<number>;
InvoiceAddress: KnockoutObservable<Address>;
constructor()
{
this.ID = ko.observable(0);
this.InvoiceAddress= ko.observable(new Address());
this.InvoideAddress.subscribe(function(newvalue) { console.log(newvalue)}, this);
}
}
属性 InvoiceAddress
另一种Address
可以是null
当用户创建或删除 InvoiceAddress
时,将发送 $ajax
请求并返回新的 JSON 对象,其中包含整个 viewmodel
的更新数据。
收到的数据映射到同一视图模型实例
ko.mapping.fromJSON(data, {}, viewmodel);
如果 InvoiceAddress
的状态从 null
更改为现有对象,则 InvoiceAddress
的绑定将停止工作。
<input data-bind="value: InvoiceAddress().StreetName">
问题:在 "re-mapping" 之后是否可以继续绑定?
更新:"Stops working" -> "InvoiceAddress" 变量中属性的订阅者在 "InvoiceAddress" 变为 null
并重新映射回普通对象后未触发
不要这样做。
<input data-bind="value: InvoiceAddress().StreetName">
这样做:
<div data-bind="with: InvoiceAddress">
<input data-bind="value: StreetName">
</div>
比较:
ko.applyBindings({
InvoiceAddress: ko.observable({StreetName: "Invoice Street"}),
ShippingAddress: ko.observable(null),
addShipping: function () { this.ShippingAddress({StreetName: "Shipping Street"}); },
removeShipping: function () { this.ShippingAddress(null); }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<b>Invoice Address</b>
<div data-bind="with: InvoiceAddress">
<input data-bind="value: StreetName">
</div>
<b>Shipping Address</b>
<div data-bind="ifnot: ShippingAddress">-</div>
<div data-bind="with: ShippingAddress">
<input data-bind="value: StreetName">
</div>
<button data-bind="click: addShipping">Add Shipping</button>
<button data-bind="click: removeShipping">Remove Shipping</button>
使用 with
还可以更轻松地将整个事物变成模板或组件。
我接受了@Tomalak 的回答,因为他的回答让我朝着正确的方向去理解 Knockout 的 Observables
是如何工作的(文档还不够 :))
但是想post一个解决问题的方法
具体问题是在 属性 被 knockout.mapping
插件从 null
映射到新对象
后订阅者停止触发
var orderData = {"ID":2,"InvoiceAddress":null}
ko.mapping.FromJS(orderData, {}, viewmodel);
//underlying object of observable this.InvoiceAddress is null
// then user added new address
var newAddressData = {"ID":3, "StreetName":"Third"} //returned by ajax request
ko.mapping.FromJS(newAddressData, {}, this.InvoiceAddress);
在那之后 this.InvoiceAddress
内的属性订阅者停止触发。
问题是因为映射插件每次都创建了 属性 类型的新实例,而没有使用初始化订阅者的类型的构造函数。
解决方案:在映射之前创建基础类型的实例
var newAddressData = {"ID":3, "StreetName":"Third"}
var tempAddress: Address = new Address();
ko.mapping.FromJS(newAddressData; {}, tempAddress);
this.InvoiceAddress(tempAddress);
ViewModel 从 JSON 初始化并映射到 $(document).ready(..)
$(document).ready(function ()
{
viewmodel = new Order();
var data = { json data };
ko.mapping.fromJSON(data, {}, viewmodel);
ko.applyBindings(viewmodel);
});
class Order
{
ID: KnockoutObservable<number>;
InvoiceAddress: KnockoutObservable<Address>;
constructor()
{
this.ID = ko.observable(0);
this.InvoiceAddress= ko.observable(new Address());
this.InvoideAddress.subscribe(function(newvalue) { console.log(newvalue)}, this);
}
}
属性 InvoiceAddress
另一种Address
可以是null
当用户创建或删除 InvoiceAddress
时,将发送 $ajax
请求并返回新的 JSON 对象,其中包含整个 viewmodel
的更新数据。
收到的数据映射到同一视图模型实例
ko.mapping.fromJSON(data, {}, viewmodel);
如果 InvoiceAddress
的状态从 null
更改为现有对象,则 InvoiceAddress
的绑定将停止工作。
<input data-bind="value: InvoiceAddress().StreetName">
问题:在 "re-mapping" 之后是否可以继续绑定?
更新:"Stops working" -> "InvoiceAddress" 变量中属性的订阅者在 "InvoiceAddress" 变为 null
并重新映射回普通对象后未触发
不要这样做。
<input data-bind="value: InvoiceAddress().StreetName">
这样做:
<div data-bind="with: InvoiceAddress">
<input data-bind="value: StreetName">
</div>
比较:
ko.applyBindings({
InvoiceAddress: ko.observable({StreetName: "Invoice Street"}),
ShippingAddress: ko.observable(null),
addShipping: function () { this.ShippingAddress({StreetName: "Shipping Street"}); },
removeShipping: function () { this.ShippingAddress(null); }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<b>Invoice Address</b>
<div data-bind="with: InvoiceAddress">
<input data-bind="value: StreetName">
</div>
<b>Shipping Address</b>
<div data-bind="ifnot: ShippingAddress">-</div>
<div data-bind="with: ShippingAddress">
<input data-bind="value: StreetName">
</div>
<button data-bind="click: addShipping">Add Shipping</button>
<button data-bind="click: removeShipping">Remove Shipping</button>
使用 with
还可以更轻松地将整个事物变成模板或组件。
我接受了@Tomalak 的回答,因为他的回答让我朝着正确的方向去理解 Knockout 的 Observables
是如何工作的(文档还不够 :))
但是想post一个解决问题的方法
具体问题是在 属性 被 knockout.mapping
插件从 null
映射到新对象
var orderData = {"ID":2,"InvoiceAddress":null}
ko.mapping.FromJS(orderData, {}, viewmodel);
//underlying object of observable this.InvoiceAddress is null
// then user added new address
var newAddressData = {"ID":3, "StreetName":"Third"} //returned by ajax request
ko.mapping.FromJS(newAddressData, {}, this.InvoiceAddress);
在那之后 this.InvoiceAddress
内的属性订阅者停止触发。
问题是因为映射插件每次都创建了 属性 类型的新实例,而没有使用初始化订阅者的类型的构造函数。
解决方案:在映射之前创建基础类型的实例
var newAddressData = {"ID":3, "StreetName":"Third"}
var tempAddress: Address = new Address();
ko.mapping.FromJS(newAddressData; {}, tempAddress);
this.InvoiceAddress(tempAddress);