javascript - tipos - ¿Por qué una función se comporta como un cálculo?
prompt javascript (2)
Eso sucede porque el método isSelected()
accede a la propiedad selectedId
(que es observable
). Considera esto:
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 .
Como puede ver, la única diferencia entre esas funciones es que la primera verifica el valor de una propiedad del modelo definida como ko.observable
. Por lo tanto, cada vez que se cambia self.selectedId
, se notifica a esta función (lo que significa que se vuelve a ejecutar).
Tenga en cuenta que si suelta la parte de vinculación de data-bind
correspondiente, este método no se ejecutará en la fase de inicialización de la vista, por lo que no se registrará como un observador adecuado.
El segundo método, aunque invocado también en la fase de inicialización, no intenta verificar el valor de Id selectedId
, por lo que no está registrado como el observador de este valor y no se invoca posteriormente.
Dado el siguiente 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());
});
Una lista se muestra. Al hacer clic en una fila, la identificación de la fila se almacena en selectedId
.
No entiendo, por qué la función isSelected
se vuelve a evaluar, cuando se cambia el isSelected
selectedId
. Después de todo, esto no se computa. ¿Por qué se vuelve a evaluar de todos modos?
Knockout utiliza observables calculados para actualizar los enlaces. Es algo como esto (modificado de bindingAttributeSyntax.js ):
ko.computed({
read: function() {
bindingHandler.update(node, getValueAccessor(bindingKey), allBindings,
bindingContext.$data, bindingContext);
},
disposeWhenNodeIsRemoved: node
});
Por lo tanto, cualquier elemento observable al que acceda para obtener el valor del enlace se convertirá en dependencias de este observable calculado y hará que el enlace se actualice.