Knockout.JS - What exactly is happening with the observable in this example?

StackOverflow https://stackoverflow.com/questions/8304540

  •  25-10-2019
  •  | 
  •  

سؤال

I'm currently trying to learn Knockout.JS - I'm also relatively new to JavaScript itself.

There is an example on the website - http://knockoutjs.com/examples/clickCounter.html - that I am currently trying to wrap my head around.

I've put some comments into the code below with what I think is going on. And there is a question there about how the function is working.

It would be great if someone more experienced in Knockout could explain exactly what is going on there. Thanks.

 (function() {  

    var clickCounterViewModel = function () {

    // Here it looks like numberOfClicks is assigned the value 0 and wrapped in a ko.observable method 
    // that allows any changes of it to ripple throughout the application.
    this.numberOfClicks = ko.observable(0);  

    //  A function is created called registerClick and assigned to the ViewModel.
    //  The value of numberOfClicks is currently 0.  
    this.registerClick = function () {

        //  numberOfClicks is being used here as a method, but it was created as a property.
        //  It almost looks like I could write:  this.numberOfClicks = this.numberOfClicks() + 1,
        //  however, that doesn't work.  this.numberOfClicks is being passed into itself as an argument.
        //  Is this some sort of recursion?  Can someone familiar with Knockout please explain how this is working?
        this.numberOfClicks(this.numberOfClicks() + 1);  
    }

    this.hasClickedTooManyTimes = ko.dependentObservable(function () {
        return this.numberOfClicks() >= 3;
    }, this);
};

ko.applyBindings(new clickCounterViewModel());      


});
هل كانت مفيدة؟

المحلول

I take it your confusion is with this line:

this.numberOfClicks(this.numberOfClicks() + 1);  

numberOfClicks is an observable, not a number, so + isn't defined for it.

When calling numberOfClicks() that "unwraps" the observable into the underlying value (the number). I believe that calling an observable as a function with a single argument updates the value, so this.numberOfClicks(1+1) would set the value of numberOfClicks to 2.

نصائح أخرى

this.numberOfClicks; is an observable. This is a special type KnockoutJs put in to allow you to two-way bind to dom elements. Whenever this property is changed, any dom elements that are bound to it will automatically update their value.

You access and set observables as though they were functions, since they actually are functions under the covers.

clickCounterViewModel.numberOfClicks(99);
var numClicksInViewModel = clickCounterViewModel.numberOfClicks(99);
//numClicksInViewModel == 99

this.hasClickedTooManyTimes is a dependentObservable, which is similar to an observable, except it's a function. Like regular observables, these can be bound to dom elements as well. When hasClickedTooManyTimes is executed, Knockout will keep track—under the covers—of which observables it relies on, and whenever any of them change, the binding system will know to update anything that is bound to hasClickedTooManyTimes

So for this particular example:

this.hasClickedTooManyTimes = ko.dependentObservable(function () {
    return this.numberOfClicks() >= 3;
}, this);

Whenever numberOfClicks gets updated, anything bound to hasClickedTooManyTimes will automatically update itself.

And that this parameter that you pass to the dependentObservable function is just a little syntactic sugar to get this to behave properly.

Here's the fantastic video that first introduced me to KnockoutJS

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top