Why does the function behave as calculated?

Given the following HTML / JS ( http://jsfiddle.net/mgs_jsfiddle/gUhm2/ )

<div data-bind="foreach: users"> <p data-bind="click: $root.onClick"> <span data-bind="text: id"></span> <span data-bind="text: firstName"></span> <span data-bind="text: $root.isSelected($data)"></span> </p> </div> $(function() { function ViewModel() { var self = this; self.users = [ { id: 1, firstName: "Bob" }, { id: 2, firstName: "David" }, { id: 3, firstName: "Walter" } ]; self.selectedId = ko.observable(1); self.isSelected = function(user) { return user.id === self.selectedId() ? "YES" : "NO"; }; self.onClick = function(user) { self.selectedId(user.id); } }; ko.applyBindings(new ViewModel()); }); 

A list is displayed. By clicking a row, the row identifier is saved in selectedId .

I do not understand why the isSelected function isSelected reevaluated when the selectedId changes. In the end, it is not calculated. Why is this being overestimated?

+6
source share
2 answers

This is because the isSelected() method accesses the selectedId ( observable ) property. Consider this:

HTML

 <!-- adding into the foreach: block --> <span data-bind="text: $root.someFunc()"></span> <span data-bind="text: $root.someOtherFunc()"></span> 

Js

 // adding to a model definition self.someFunc = function() { self.selectedId(); console.log('I AM AN OBSERVER'); return 'oi: ' + Math.random(); }; self.someOtherFunc = function() { // self.selectedId(); console.log('AND I AM NOT'); return 'no: ' + Math.random(); } 

Fiddle

As you can see, the only difference between these functions is that the first checks the value of the model property defined as ko.observable . Therefore, every time self.selectedId changes, this function is notified about this (which effectively means repeating it).

Please note that if you drop the corresponding part of the data-bind , this method will not be launched in the initialization phase of the view, so it will not be able to register as the correct observer.

The second method, although called during the initialization phase, also does not try to check the selectedId value, so it is not registered as this value observer and is not called later.

+6
source

Knockout uses calculated observables to update bindings. This is something like this (changed from bindingAttributeSyntax.js ):

 ko.computed({ read: function() { bindingHandler.update(node, getValueAccessor(bindingKey), allBindings, bindingContext.$data, bindingContext); }, disposeWhenNodeIsRemoved: node }); 

That way, any observables you get to get the binding value will become dependent on that computed observable and cause the update to bind.

+1
source

Source: https://habr.com/ru/post/953790/


All Articles