Knockout Dependency Tracking
Computed values only depend on the observables they reference.
HTML
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<script id="tmpl-1" type="text/html">
<div>Template 12</div>
<div data-bind="text: dependency1"></div>
</script>
<strong>Dependency1</strong>
<p id="pd1" data-bind="text: dependency1"></p>
<strong>Dependency2</strong>
<p data-bind="text: dependency2"></p>
<strong>Computed (depends on Dependency1)</strong>
<p data-bind="text: computed"></p>
<strong>Template 1</strong>
<div data-bind="template: 'tmpl-1'"></div>
<button data-bind="click: changeDependency1">Change Dependency1</button>
<button data-bind="click: changeDependency2">Change Dependency2</button>
JavaScript
// Intercept calls to binding provider and when applying bindings
//
// Proof of concept
//
(function (ko) {
var snapshot = false;
var debug = {
log: function () {
var time = "",
now = new Date().getTime();
if (snapshot) {
time = "+" + (now - snapshot).toString();
}
if (console.log) {
console.log("[profiler]" + time, arguments);
}
snapshot = now;
}
};
var super_instance = ko.bindingProvider['instance'],
super_applyBindings = ko.applyBindings,
super_getBindings = ko.bindingProvider['instance']['getBindings'],
init = true;
var fnSubscriptionChange = function (key, model) {
return function (newValue) {
// A value has changed outside of initialization
init = false;
// Log it
debug.log("CHANGE: (" + key + "), Updating subscriptions: " +
(model[key]['getSubscriptionsCount']() - 1).toString());
};
};
ko.applyBindings = function (viewModel, node) {
snapshot = new Date().getTime();
debug.log("ATTACH:", viewModel);
for (var key in viewModel) {
if (viewModel[key]['subscribe']) {
debug.log("SUBSCRIBE: " + key);
viewModel[key]['subscribe'](fnSubscriptionChange(key, viewModel));
}
}
return super_applyBindings.apply(this, arguments);
};
ko.bindingProvider['instance']['getBindings'] = function (node, bindingContext) {
var bindings = super_getBindings.apply(super_instance, [node, bindingContext]),
viewModel = bindingContext['$root'],
observables = [],
properties = [];
if (init) {
return bindings;
}
for (var property in...