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:
rateLimit extender
There is a new rateLimit
extender that handles throttle and debounce scenarios (docs here). Some notes about this functionality:
- The
throttle
extender is deprecated. There are some slight differences betweenrateLimit
andthrottle
described here. - The
rateLimit
extender returns the original value rather than a new computed like thethrottle
extender. 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 anisValid
sub-observable, which became inaccessible when thethrottle
extender created a new computed to stand in front of it. - The
rateLimit
extender works properly with observables, computeds, and observableArrays. - It supports a
method
option that by default is set tonotifyAtFixedRate
which corresponds to a throttling strategy. For a debounce scenario, the method can be set tonotifyWhenChangesStop
.
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.
The 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 rateLimit
.
Link to full sample on jsFiddle.net
valueAllowUnset option
There is now a valueAllowUnset
option for scenarios where the value
does not match what is contained in the options
:
- 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.
1
|
|
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.
ko.computedContext
- 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.computedContext
while evaluating a computed, you have access to theisInitial
andgetDependenciesCount
functions:
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 |
|
Use __proto__
for base types
In browsers that support it, the base types (ko.subscribable
, ko.observable
, ko.computed
, 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 jQuery
when 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 jQuery
.
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.