mobservable
Advanced tools
Comparing version 1.0.0 to 1.0.1
@@ -0,1 +1,5 @@ | ||
# 1.0.1 | ||
* Stricter argument checking for several api's. | ||
# 1.0 | ||
@@ -2,0 +6,0 @@ |
@@ -118,2 +118,14 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
return observableDecorator.apply(null, arguments); | ||
switch (arguments.length) { | ||
case 0: | ||
throw new Error("[mobservable.observable] Please provide at least one argument."); | ||
case 1: | ||
break; | ||
case 2: | ||
if (typeof v === "function") | ||
break; | ||
throw new Error("[mobservable.observable] Only one argument expected."); | ||
default: | ||
throw new Error("[mobservable.observable] Too many arguments. Please provide exactly one argument, or a function and a scope."); | ||
} | ||
if (isObservable(v)) | ||
@@ -163,2 +175,6 @@ return v; | ||
var _a = getValueModeFromValue(view, ValueMode.Recursive), mode = _a[0], unwrappedView = _a[1]; | ||
if (typeof unwrappedView !== "function") | ||
throw new Error("[mobservable.autorun] expects a function"); | ||
if (unwrappedView.length !== 0) | ||
throw new Error("[mobservable.autorun] expects a function without arguments"); | ||
var observable = new observableview_1.ObservableView(unwrappedView, scope, { | ||
@@ -208,3 +224,3 @@ object: scope || view, | ||
if (!dnode_1.isComputingView()) | ||
throw new Error("[mobservable.expr] 'expr' can only be used inside a computed value."); | ||
console.warn("[mobservable.expr] 'expr' should only be used inside other reactive functions."); | ||
return observable(expr, scope)(); | ||
@@ -218,7 +234,4 @@ } | ||
function observableDecorator(target, key, baseDescriptor) { | ||
// - In typescript, observable annotations are invoked on the prototype, not on actual instances, | ||
// so upon invocation, determine the 'this' instance, and define a property on the | ||
// instance as well (that hides the propotype property) | ||
// - In typescript, the baseDescriptor is empty for attributes without initial value | ||
// - In babel, the initial value is passed as the closure baseDiscriptor.initializer' | ||
if (arguments.length < 2 || arguments.length > 3) | ||
throw new Error("[mobservable.@observable] A decorator expects 2 or 3 arguments, got: " + arguments.length); | ||
var isDecoratingGetter = baseDescriptor && baseDescriptor.hasOwnProperty("get"); | ||
@@ -225,0 +238,0 @@ var descriptor = {}; |
{ | ||
"name": "mobservable", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Observable data. Reactive functions. Simple code.", | ||
@@ -5,0 +5,0 @@ "main": "dist/mobservable.js", |
@@ -19,11 +19,8 @@ # mobservable | ||
Next to that it can make your functions (or [React components](https://github.com/mweststrate/mobservable-react)) reactive, so that they re-evaluate whenever relevant data is altered. | ||
It's like Excel for JavaScript: any data structure can be turned into a 'data cell', any function into a 'formula' that updates automatically. | ||
It's like Excel for JavaScript: any data structure can be turned into a 'data cell', and every function or user interface component can be turned into a 'formula' that updates automatically. | ||
Mobservable is unopiniated about which data structures to use; | ||
it can work with mutable objects, arrays, (cyclic) references, classes etc. | ||
So that your actions, stores and user interface can remain KISS. | ||
Besides that, it is [fast](mendix.com/tech-blog/making-react-reactive-pursuit-high-performing-easily-maintainable-react-apps/). | ||
This has major benefits for the simplicity, maintainability and performance of your code: | ||
* Write complex applications which unmatched simple code. | ||
* Enable unopiniated state management: be free to use mutable objects, cyclic references, classes and real references to store state. | ||
* Write declarative views that track their own dependencies. No subscriptions, cursors or other redundant declarations to manage. | ||
* Build [high performing](mendix.com/tech-blog/making-react-reactive-pursuit-high-performing-easily-maintainable-react-apps/) React applications without Flux or Immutable data structures. | ||
* Predictable behavior: all views are updated synchronously and atomically. | ||
## The essentials | ||
@@ -52,14 +49,5 @@ | ||
Without Mobservable, this app would do nothing beyond the initial render. | ||
The timer would increase every second, but the would UI never update. | ||
To fix that, your code should trigger the UI to update each time the `timerData` changes. | ||
But there is a better way. | ||
We shouldn't have to _pull_ data from our state to update the UI. | ||
Instead, the data structures should be in control and call the UI whenever it becomes stale. | ||
The state should be _pushed_ throughout our application. | ||
In the example above the `timerData` data structure is made observable and the `Timer` component is turned into an `observer`. | ||
Mobservable will automatically track all relations between _observable data_ and _observing functions (or components)_ so that the minimum amount of observers is updated to keep all observers fresh. | ||
In the example above this is achieved by making the `timerDate` observable and by turning the `Timer` component into an `observer`. | ||
Mobservable will automatically track all relations between _observable data_ and _observing functions (or components)_ so that the minum amount of observers is updated to keep all observers fresh. | ||
Its as simple as that. In the example above the `Timer` will automatically update each time the property `timerData.secondsPassed` is altered. | ||
@@ -69,12 +57,10 @@ The actual interesting thing about this approach are the things that are *not* in the code: | ||
* The `setInterval` method didn't alter. It still treats `timerData` as a plain JS object. | ||
* There is no state. Timer is a dumb component. | ||
* There is no magic context being passed through components. | ||
* If the `Timer` component would be somewhere deep in our app; only the `Timer` would be re-rendered. Nothing else (sideways data loading). | ||
* There are no subscriptions of any kind that need to be managed. | ||
* There is no forced UI update in our 'controller'. | ||
* There is no state in the component. Timer is a dumb component. | ||
* This approach is unobtrusive; you are not forced to apply certain techniques like keeping all data denormalized and immutable. | ||
* There is no higher order component that needs configuration; no scopes, lenses or cursors. | ||
* There is no forced UI update in our 'controller'. | ||
* If the `Timer` component would be somewhere deep in our app; only the `Timer` would be re-rendered. Nothing else. | ||
* There is no magic context being passed through components. | ||
All this missing code... it will scale well into large code-bases! | ||
It does not only work for plain objects, but also for arrays, functions, classes, deeply nested structures. | ||
## Getting started | ||
@@ -86,2 +72,17 @@ | ||
## Top level api | ||
For the full api, see the [API documentation](https://mweststrate.github.io/mobservable/refguide/observable.html). | ||
This is an overview of most important functions available in the `mobservable` namespace: | ||
**observable(value, options?)** | ||
The `observable` function is the swiss knife of mobservable and enriches any data structure or function with observable capabilities. | ||
**autorun(function)** | ||
Turns a function into an observer so that it will automatically be re-evaluated if any data values it uses changes. | ||
**observer(reactJsComponent)** | ||
The `observer` function (and ES6 decorator) from the `mobservable-react` turns any Reactjs component into a reactive one. | ||
From there on it will responds automatically to any relevant change in _observable_ data that was used by its render method. | ||
## Examples | ||
@@ -104,17 +105,2 @@ | ||
## Top level api | ||
For the full api, see the [API documentation](https://mweststrate.github.io/mobservable/refguide/observable.html). | ||
This is an overview of most important functions available in the `mobservable` namespace: | ||
**observable(value, options?)** | ||
The `observable` function is the swiss knife of mobservable and enriches any data structure or function with observable capabilities. | ||
**autorun(function)** | ||
Turns a function into an observer so that it will automatically be re-evaluated if any data values it uses changes. | ||
**observer(reactJsComponent)** | ||
The `observer` function (and ES6 decorator) from the `mobservable-react` turns any Reactjs component into a reactive one. | ||
From there on it will responds automatically to any relevant change in _observable_ data that was used by its render method. | ||
## What others are saying... | ||
@@ -121,0 +107,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1850
86233
119