Knockout version 3.1 is available now! This was a nice incremental release with a few new features, some performance enhancements, and a number of bug fixes. For a complete list of changes, check out the release notes.
Here are some of my favorite changes:
There is a new
rateLimit extender that handles throttle and debounce scenarios (docs here). Some notes about this functionality:
throttleextender is deprecated. There are some slight differences between
rateLimitextender returns the original value rather than a new computed like the
throttleextender. This saves the overhead of an additional computed and better handles scenarios where the original value has already been extended in other ways (perhaps the original had an
isValidsub-observable, which became inaccessible when the
throttleextender created a new computed to stand in front of it.
rateLimitextender works properly with observables, computeds, and observableArrays.
- It supports a
methodoption that by default is set to
notifyAtFixedRatewhich corresponds to a throttling strategy. For a debounce scenario, the method can be set to
For example, suppose that we define three observableArrays.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
In the jsFiddle below, when you click the “Start” button, a new item will be pushed to each observableArray every 100ms for 100 iterations to demonstrate the behavior under each option.
rateLimit extender will be a key tool going forward. I feel that after upgrading to 3.1 it would be worthwhile to review existing uses of the
throttle extender in an app and update to
There is now a
valueAllowUnset option for scenarios where the
value does not match what is contained in the
- With this option set to true, Knockout does not force the value to match an existing option.
- The selection will be set to an empty option in the case of a mismatch, but the value is not overwritten.
- This is very useful in scenarios where options are lazily loaded and there is an existing value.
In this example, `selectedCategory` may be loaded with a value from the database and then when an editor is shown `categories` are loaded via an AJAX request. Without the `valueAllowUnset` option, Knockout would have recognized that the value of `selectedCategory` did not match an available option and tried to set it to the first option or undefined if there are no options. Without taking care to cache the original value, `selectedCategory` would have lost its value.
- You can now access the dependency count and whether it is the first evaluation within a computed. This could be useful in scenarios where you know that the function will never be called again (no dependencies) or to run special logic (or avoid logic) when it is the first evaluation. By using
ko.computedContextwhile evaluating a computed, you have access to the
1 2 3 4 5 6 7 8 9 10 11 12 13
array methods pass index
The array utility methods now pass the array index as the second argument to the callbacks (in addition to the array item as the first argument).
1 2 3 4
__proto__ for base types
In browsers that support it, the base types (
ko.observableArray) now use the
fn objects as their prototype rather than copying functions from the
fn objects to the result (since the result itself is a function, in older browsers it is not possible to set the prototype for it).
Dependency tracking performance enhancement
Dependencies are tracked in objects with unique ids, rather than in an array on each subscribable. This eliminates the need to loop internally to find an existing dependency, which has caused long-running script errors in older browsers when there were a large number of dependencies for a single observable/computed.
Look for jQuery later
Knockout looks for
applyBindings is called rather than when KO is loaded. This helps eliminate an issue with the order that KO and jQuery are loaded and in an AMD scenario you would not have to add
jQuery as a dependency to KO in the shim configuration to have KO take advantage of
There are many additional fixes listed in the release notes here. Please log any issues related to 3.1 to GitHub. Michael Best again did a tremendous job with the bulk of the changes along with Steve Sanderson as well as a number of community contributors.