我不认为你做错了什么。问题是在更新与“with”的绑定之前,正在应用与 root.isEmployee 的“if”绑定。因此代码正在查看对 isEmployee 的更新,然后从那里重新评估视图,但当前上下文仍然是老人(因为该订阅尚未触发)。
这可以通过http://jsfiddle.net/drdamour/X6pC9/2/中的自定义绑定来证明, 请注意更新接收 2 个事件,一次使用旧值导致 isEmployee 更新,第二次使用更新后的新值。第二次更新来自被触发的“with”绑定订阅。'with' 绑定的订阅发生在 applyBindings 调用期间,这发生在您的模型进行订阅之后。
您可以使用 $data.PropertyName 技巧来处理未定义的不引起问题的问题。阿拉:http: //jsfiddle.net/drdamour/X6pC9/1/
<span data-bind="with: person">
<span data-bind="text: firstName"></span>
<!-- ko if: $root.isEmployee -->
<span data-bind="text: $data.employeeId"></span>
<span data-bind="text: $data.employer"></span>
<!-- /ko -->
</span>
解决这个问题的正确方法是拥有一个计算 isEmployee 的 PersonVM,这样你就不会绑定到根。见:http: //jsfiddle.net/drdamour/eVXTF/1/
<span data-bind="with: person">
<span data-bind="text: firstName"></span>
<!-- ko if: isEmployee -->
<span data-bind="text: $data.employeeId"></span>
<span data-bind="text: $data.employer"></span>
<!-- /ko -->
</span>
和
var ViewModel = function(){
var self = this;
self.person = ko.observable();
};
var PersonVM = function()
{
var self = this;
this.firstName = ko.observable();
this.employeeId = ko.observable();
this.employer = ko.observable();
self.isEmployee = ko.computed(function(){return self.employer() != null});
}
var vm = new ViewModel();
var customer = new PersonVM();
customer.firstName("John");
var employee = new PersonVM();
employee.firstName("Bill");
employee.employeeId(123);
employee.employer("ACME");
vm.person(customer);
ko.applyBindings(vm);
setTimeout(function(){ vm.person(employee); }, 3000);
计算优先于订阅方法,因为它为您处理订阅链并将您从必须管理的所有内容中抽象出来。