0

コンテキストに関する限り、何かが欠けていると確信していますが、何がわかりません。

次のViewModelがあります:

var ViewModel = function(){
    var self = this;
    self.person = ko.observable();
    self.isPerson = ko.observable();

    self.person.subscribe(function(value){
        self.isPerson('firstName' in value);
    });
};

var vm = new ViewModel();
var personA = { };
var personB = { firstName: ko.observable("hello") };

vm.person(personA);
ko.applyBindings(vm);
setTimeout(function(){ vm.person(personB); }, 1000);

および次のビュー:

<span data-bind="with: person">
    <!-- ko if: $root.isPerson -->
        <span data-bind="text: firstName"></span> 
    <!-- /ko -->    
</span>

JSFiddle

タイムアウトが実行されると、firstName がビューに表示されると思いますが、次のエラーが発生します。

 firstName is not defined;

viewModel で personB から始めると、うまくいきます。if ステートメントを with ステートメントの上に移動すると、機能します。

このシナリオで何が間違っていますか?

更新された JSFiddle

4

1 に答える 1

3

あなたが何か間違ったことをしているとは思いません。問題は、「with」へのバインディングが更新される前に、root.isEmployee への「if」バインディングが適用されることです。そのため、コードは isEmployee への更新を確認し、そこからビューを再評価していますが、現在のコンテキストはまだ古い人です (そのサブスクリプションが起動されていないため)。

これは、 http://jsfiddle.net/drdamour/X6pC9/2/のカスタム バインディングによって証明されています 。更新が 2 つのイベントを受け取ることに注意してください。この 2 番目の更新は、トリガーされた "with" バインディング サブスクリプションから発生します。「with」バインディングのサブスクリプションは、モデルがサブスクリプションを実行した後に発生する applyBindings 呼び出し中に発生します。

$data.PropertyName トリックを使用して、undefined ではない問題に対処できます。アラ: 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);

計算されたメソッドは、サブスクライブ チェーンを処理し、そのすべてを管理する必要がなくなるため、サブスクライブ メソッドよりも優先されます。

于 2013-01-22T05:16:09.563 に答える