Skip to content

Commit c1e0c14

Browse files
committed
docs: lifecycle draft; expressions
Closes angular#578
1 parent 6f59f2f commit c1e0c14

File tree

7 files changed

+251
-6
lines changed

7 files changed

+251
-6
lines changed

modules/angular2/docs/change_detection/change_detection.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Change Detection
22

3+
Change Detection is a mechanism of detecting changes in the model so that they can be propageted to the destination. Changes are detected and propageted in a top down manner from the root View to the child Views in a depth first traversal.
4+
5+
6+
## `ChangeDetector`s
7+
8+
Each View has an associated `ChangeDetector` class with it. (Some Views may have more than one `ChangeDetector` to support partial views updates as is the case with `[hidden]` bindings.) `ChangeDetector`s are arranged in
9+
10+
11+
12+
13+
314
* Mechanisms by which changes are detected in the model
415
* DAG
516
* Order of evaluation
Lines changed: 163 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,167 @@
1-
# Expressions
1+
# Expressions and Statements
2+
3+
Expressions and statements are small code snippets which are placed in the Angular templates. Following example shows where in the template can expressions and statements be located.
4+
5+
```
6+
<h1>{{expression}}</h1>
7+
<div [property1]="expression" property2="{{expression}}">
8+
<button (click)="statement">OK</button>
9+
<div !foreach="#varName in expression">...</div>
10+
```
11+
12+
<table>
13+
<tr>
14+
<th></th>
15+
<th>Expressions</th>
16+
<th>Statements</th>
17+
</tr>
18+
<tr>
19+
<th>Used in:</th>
20+
<td>String in; Property binding; Template binding</td>
21+
<td>Events</td>
22+
</tr>
23+
<tr>
24+
<th>Execution</th>
25+
<td>During Change Detection</td>
26+
<td>Due to event before Change Detection</td>
27+
</tr>
28+
<tr>
29+
<th>Null dereference</th>
30+
<td>Forgiving / Silent</td>
31+
<td>Error</td>
32+
</tr>
33+
<tr>
34+
<th>Idempotent (side-effects)</th>
35+
<td>NO</td>
36+
<td>YES</td>
37+
</tr>
38+
<tr>
39+
<th>Assignments</th>
40+
<td>Not allowed</td>
41+
<td>Allowed</td>
42+
</tr>
43+
<tr>
44+
<th>Multiple</th>
45+
<td>Single expression</td>
46+
<td>Multiple statements separated by ';'</td>
47+
</tr>
48+
<tr>
49+
<th>Formatters</th>
50+
<td>Allowed at an end of expression only</td>
51+
<td>Not allowed</td>
52+
</tr>
53+
</table>
54+
55+
56+
57+
## Expressions
58+
59+
Expressions are bindings which are executed as part of the Change Detection. While Change Detection guarantees that the changes are delived in the order in which they are declared in the template, the individual sub-parts of the expressions may be executed in any order due to sub-expression coelescence.
60+
61+
Example `<span>Hello: {{user.last}}, {{user.first}}</span>` is made up of `user`, `last`, and `first`. The change detection may chose to evaluate the `user` only once since it is a common sub-expression for the two expressions used in the binding.
62+
63+
Expressions are forgiving in nature. In the above example if `user` is `null` the `user.last` will not throw an error, instead it will result in an `null` which will consequently be rendered as an empty string. This is done because during the data loading it is very common for sub-expressions to not be defined yet and placing guards around each expressions would result in too much boilerplate.
64+
65+
66+
### Expressions Semantics
67+
68+
The expressions follow the semantics of the underlying platform with the exception of silent null dereferencing. This means that they follow JavaScript semantis in AngularJS, and Dart semantics in AngularDart.
69+
70+
Some example of different semantics between JavaScript and Dart:
71+
72+
- `'one' + 2`: will result in `one2` in JavaScript, but an error in Dart.
73+
- `obj['prop']`: will work for all objects in JavaScript, but only for `Map`s in Dart. (NOTE: ES6 `Map` require `obj.get('prop')`)
74+
75+
76+
### Expression Syntax
77+
78+
Expression syntax follows that of the platform, with few limitations (no assignment and no keywords: `if`, `for`, etc) and additon of Formatters.
79+
80+
Here is the list of allowed operations in Angular Expressions.
81+
82+
<table>
83+
<tr>
84+
<th>Name</th>
85+
<th>Syntax</th>
86+
<th>Notes</th>
87+
</tr>
88+
<tr>
89+
<th>Dereference</th>
90+
<td>`obj.prop`</td>
91+
<td>Silently ignores if `obj` is `null` or `undefined`.</td>
92+
</tr>
93+
<tr>
94+
<th>Map</th>
95+
<td>`obj[key]`</td>
96+
<td>Silently ignores if `obj` is `null` or `undefined`. <br> JavaScript treats `obj.prop` and `obj['prop']` same, but Dart only allows `obj['prop']` on Maps.</td>
97+
</tr>
98+
<tr>
99+
<th>Operators:</th>
100+
<td>`+`, `-`, `/`, `*`, <br>`<`, `<=`, `<>`, `>=`, <br> `==`, `!=` <br> `!`</td>
101+
<td>JavaScript does type coercion, Dart requires types to match. </td>
102+
</tr>
103+
<tr>
104+
<th>Invocation</th>
105+
<td>`fn(args)`</td>
106+
<td></td>
107+
</tr>
108+
<tr>
109+
<th>Formatters</th>
110+
<td>expr | formatter:arg0:...</td>
111+
<td>Formatters must be at the end of the expression. The formatter arguments are separated by `:`, which in turn can be expressions. </td>
112+
</tr>
113+
<tr>
114+
<th>Truthyness</th>
115+
<td></td>
116+
<td>In Dart only values which are `Boolean` and `true` are consider truthy. In JavaScript type coercion allows many other things to be consider true.</td>
117+
</tr>
118+
</table>
119+
2120

3-
## Binding Semantics
4121

5122
### Formatters
6123

7-
## Statement Semantics
124+
Formatters are pure functions which can transform the input model to a different more usable data format. Examples include converting `Date` type to localized string or limiting the items in an array for filtering of `Foreach` items in a repeater.
125+
126+
Formatters can only be placed at the end of an `expression` (i.e. they can not be part of sub-expressions.) Formatters can be chained together, where the output of one formatter becomes an input of the next.
127+
128+
Formatters can take arguments, which are themselves an `expression`s separetd by `:`.
129+
130+
Here are some examples:
131+
132+
- `date | localizedDate` - Example of a formatter.
133+
- `date | localizedDate:'short'` - Example of a formatter takeing an argument.
134+
- `map | toArray | filter:predicate` - Example of formatter chaining.
135+
136+
137+
## Statement Semantics
138+
139+
Statements execute in response to an event. Syntactically statements are identical to expressions with few differences:
140+
141+
1. assignments are allowed
142+
2. `null` dereference is an error
143+
3. multiple statements separated by `;`
144+
4. Formatters are not allowed.
145+
146+
<table>
147+
<tr>
148+
<th>Name</th>
149+
<th>Syntax</th>
150+
<th>Notes</th>
151+
</tr>
152+
<tr>
153+
<th>Dereference</th>
154+
<td>`obj.prop`, `obj[key]`</td>
155+
<td>Throws if `obj` is `null` or `undefined`.</td>
156+
</tr>
157+
<tr>
158+
<th>Assignment</th>
159+
<td>`=`</td>
160+
<td>Allowed in statements only.</td>
161+
</tr>
162+
<tr>
163+
<th>Formatters</th>
164+
<td></td>
165+
<td>Not allowed in statements.</td>
166+
</tr>
167+
</table>

modules/angular2/docs/change_detection/record.md

Lines changed: 0 additions & 3 deletions
This file was deleted.

modules/angular2/docs/core/01_templates.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,15 @@ microsyntax for `foreach`.
417417
</ul>
418418
```
419419

420+
Finally, we can pull the `foreach` selector into the attribute key and prefix it with `!`.
421+
422+
```
423+
<ul>
424+
<li !foreach="var person in people; var i=index">{{i}}. {{item}}<li>
425+
</ul>
426+
```
427+
428+
420429
The format is intentionally defined freely, so that developers of directives can build expressive microsyntax for
421430
their directives. Following describes a more formal definition.
422431

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Decorators
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Instantiators
2+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Application LifeCycle
2+
3+
Application LifeCycle describes when different lifecycle events occure during the lifetime of the application. As the Angular application executes, it is helpuful to undersand different phases of execution and the philosophy behind each.
4+
5+
## Browser Event Processing
6+
7+
At its core an Angular application is tightly bound to the browser execution/event loop. This means that an Angular application can only do work in response to a browser event. These events can be due to user input, server response, or scheduled timers.
8+
9+
In order to know when the event when an even happens, the event needs to be registered inside an Angular Zone, which adds the lifecycle processing to the event. Events registered outside the Angular Zone will not be intercepted and hence will not have their bindings processed.
10+
11+
One can use the Angular Zone to controll which events should have binding side effects and which should not just by controlling in which zone event registration took place.
12+
13+
## Angular Zone Event Processing
14+
15+
The event callback usually contains the work which mutates the application state, while the data-binding contains instructions how to project the mutated state back to the UI.
16+
17+
The Angular Zone will automatically trigger the change detection at the end of each event.
18+
19+
20+
## Change Detection
21+
22+
Change Detection is a way of detecting changes to the application state and projecting these changes into the UI. The change detection starts at the root of the application and proceds to the children in the depth-first traversal. The change detection tree follows the View tree.
23+
24+
When a change is detected it is delivered to the coresponding binding. This is either the element property or the property on the directive.
25+
26+
If the directive has `onChange` method, then the `onChange` method is executed after all of the changes have been delivered to the directive. This gives the directive a chance to compute new values for child bindings (to child directives or elements)
27+
28+
Finally if a directive has `onCheck` method, it is invoked, which gives the directive a chance to perform its own change detection. Usually used with structural checks.
29+
30+
Angular's change detection is limited to the reference equality. Angular's change detection can not deep watch objects (known as structural changes). The reason for this is that structural changes are expensive. Furthermore the change delivery mechanism is usage specific. (i.e. `foreach` may want to have its changes deliverd in a animation compatible way, where as `class`-list may have more relaxed requriments.) In ordere to structuraly watch an on object the directive must use a custom structural watcher (common ones are provided) and invoke its `check` method from the `onCheck` lifecycle event.
31+
32+
33+
34+
### Directed Acyclic Graph
35+
36+
The change detection processes changes from the root to the child bindings in the depth first order. A change in parent binding, may change the application model such that a child binding may fire as a result. The parent to child flow of data is strict. The consequence of this is that the bindings form a directed (parent to child) acyclic (single pass, no stabilization) graph (DAG). This is in contrast to Angular v1.x where bindings could go in any direction (from child to parent) and they could form cycles. Cycles in the graph require multiple digest, and run the risk of not stabilizing after few iterations. This is strictly prohibited in Angular2 and is enforced in the development mode.
37+
38+
The advantages of DAG is that for large applications the flow of data is easier to reason about, performance is a lot more predictable, and it allows us to disable change detection in some branches under some circumstaces further improving performance.
39+
40+
41+
42+
## View Creation and Destruction
43+
44+
While change detection is running, a binding may cause an Instantiator directive to create, destroy, or move a View in a ViewPort.
45+
46+
Views have their own lifecycle methods which the directives can tage advantage of. A View goes through these changes.
47+
48+
- *creation* - Instantiate new View from the ProtoView. This is relativly expensive operation which involves DOM cloning and locating of the Nodes which have bindings.
49+
- *hydration* - Create associated directives for the View when the View is attached to the ViewPort.
50+
- *dehydration* - View is removed from the ViewPort and the associated directives need to be destroyed.
51+
- *cached* - A View is no longer in used, but it is cached so that a relativly expensive *creation* operation can be skipped in case someone needs a View again.
52+
- *destruction* - View is released to GC if the cache is filled up.
53+
54+
55+
# Summary
56+
57+
A directive is notified of these lifecycle events.
58+
59+
- `onHydrate()` - Right after the directive is created.
60+
- Change Detection
61+
- update bindings - A directive property (or property setter) is updated.
62+
- `onChange()` - Called to let the directive know that all of the directive properties have been updated and that there are no more changes.
63+
- `onCheck()` - Called after `onChange()` which allows the directive to perform structural changes as part of the change detection.
64+
- `onDehydrate()` - Called to let the directive know that the associated View has been destroyed.

0 commit comments

Comments
 (0)