简体   繁体   中英

Knockout : context changed before the instruction in observable.subscribe

I'm trying to separate my Model from my ViewModel since I need the Model in two different ViewModel. So i've tried to this :

var ConversationManager = {
    conversations: ko.observableArray([
        {id: 3, receiver:'Toto'}
    ])
};

function ConversationDialogViewModel(){
    var self = this;

    ConversationManager.conversations.subscribe(function(context){
        console.log('Before :', context); // context.test == true ???

        for(var i = 0; i < context.length; i++){
            if(context[i].id % 2 == 0 && !context[i].test){
                console.log('Insertion Called');
                context[i].test = true;
            }
        }
        console.log('After :', context);
    });

    ConversationManager.conversations.push({id: 4, receiver:'Jean'});
    ConversationManager.conversations.push({id: 5, receiver:'Paul'});
    ConversationManager.conversations.push({id: 6, receiver:'Bleu'});
}

Somehow, in the first console.log, when i push "Jean", in the browser, the variable "test" exists and is correctly set to true even before i actually tell JS to do it. How is that possible ? And, am I correctly separating my concerns ?

From the documentation :

If you want to be notified of the value of an observable before it is about to be changed, you can subscribe to the beforeChange event.

You could try it this way:

ConversationManager.conversations.subscribe(function(context){
    // ...
}, null, "beforeChange");

When the console references an object (where you can click an arrow to open it and look at its contents), it is still a reference, not a snapshot in time. As you modify context , it doesn't matter which reference to it in the debugger you look at, they will all be the same. You need to convert it to something that is static (or put in a breakpoint) if you want to see it at a moment in time.

 var ConversationManager = { conversations: ko.observableArray([ {id: 3, receiver:'Toto'} ]) }; function ConversationDialogViewModel(){ var self = this; ConversationManager.conversations.subscribe(function(context){ console.log('Before :', JSON.stringify(context)); // context.test == true ??? for(var i = 0; i < context.length; i++){ if(context[i].id % 2 == 0 && !context[i].test){ console.log('Insertion Called'); context[i].test = true; } } console.log('After :', JSON.stringify(context)); }); ConversationManager.conversations.push({id: 4, receiver:'Jean'}); ConversationManager.conversations.push({id: 5, receiver:'Paul'}); ConversationManager.conversations.push({id: 6, receiver:'Bleu'}); } new ConversationDialogViewModel(); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM