Skip to content

Commit 934ab8c

Browse files
author
ying.liu
committed
add smart components and presentational components
1 parent 2298b82 commit 934ab8c

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

frontend/angular-best-practices.md

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,40 @@
22

33
Here is a set of best practices using Angular.
44

5+
## Architecture: Smart Components and Presentational Components
6+
7+
The overall Angular application could be organized into two types of components: [smart components and presentational components](https://blog.angular-university.io/angular-2-smart-components-vs-presentation-components-whats-the-difference-when-to-use-each-and-why/).
8+
9+
- Smart component: aslo called application level component or container component. A smart component usually retrieves data using services and may use presentational components to display data.
10+
- Presentational components: also known as pure component or dumb component. It receives its data from parent smart component using `@Input()` binding. It uses `@Output()` event to communicate with its parent component.
11+
12+
If there are multiple level between a smart component and a presentational component, use RxJS's `subject` to communicate via a service. This should be carefully documented in all components involved in the communication.
13+
14+
The `ngrx/store` is not recommended because the depency injection and RxJS can solve most problems in a more elegent way.
15+
16+
## Change Detection Strategy
17+
18+
It is recommended to use the `ChangeDetectionStrategy.OnPush` strategy for better performance. Correspondingly, use `@Input` with immutable objects and the `async` pipe in components.
19+
20+
The default change detection strategy `ChangeDetectionStrategy.Default`runs change detection for all possible operations, thus it is not efficient in many cases. When use `ChangeDetectionStrategy.OnPush` change detection strategy, Angular runs change detection only in two cases: 1) The `@Input` reference changes (the `===` comparison changes), and 2) A DOM event such as a button click originated from the component or one of its children. It ignores all timers, promises and HTTP events. An exception is that when you use the `async` pipe to display data from asynchrounous operations like HTTP requests or promises, the `async` pipe marks the component to be checked by calling the `ChangeDetectorRef.markForCheck()` method.
21+
22+
Use asynchronous methods to update properties and know the `NgZone` concept to avoid the `ExpressionChangedAfterItHasBeenCheckedError` error.
23+
524
## Constructor and Lifecycle Hooks
625

726
For property bindings and change detection theories, check [these blogs](https://blog.angularindepth.com/these-5-articles-will-make-you-an-angular-change-detection-expert-ed530d28930).
827

928
Simply, follow the following rules:
1029

1130
- Use `constructor()` only for dependency injection.
12-
- Use `ngOninit()` to initialize data-bound properties.
13-
- Use `ngAfterViewInit()` when you need to do something after the component view is initialized. The `@ViewChild` fields are initialized when this hook is called.
31+
- Use `ngOninit()` to initialize data-bound properties or subscribe to third-party widget events.
1432
- Use `ngDestroy()` to clear resources such as unsubscribing from observables.
15-
- Use asynchronous methods to update properties and know the `NgZone` concept to avoid the `ExpressionChangedAfterItHasBeenCheckedError` error.
1633

17-
## Change Detection Strategy
34+
Use the other hooks only if you fully understand the consequences:
1835

19-
It is recommended to use the `ChangeDetectionStrategy.OnPush` strategy for better performance. Correspondingly, use `@Input` with immutable objects and the `async` pipe in components.
20-
21-
The default change detection strategy `ChangeDetectionStrategy.Default`runs change detection for all possible operations, thus it is not efficient in many cases. When use `ChangeDetectionStrategy.OnPush` change detection strategy, Angular runs change detection only in two cases: 1) The `@Input` reference changes (the `===` comparison changes), and 2) A DOM event such as a button click originated from the component or one of its children. It ignores all timers, promises and HTTP events. An exception is that when you use the `async` pipe to display data from asynchrounous operations like HTTP requests or promises, the `async` pipe marks the component to be checked by calling the `ChangeDetectorRef.markForCheck()` method.
36+
- Use `ngAfterViewInit()` when you need to do something after the component view is initialized. The `@ViewChild` fields are initialized when this hook is called.
37+
- Use `ngOnChanges()` if you want to track parent bound `@Input` properties.
38+
- Use `ngDoCheck()` if you want to track self-component peroperties and calculated properties. For example, `ngDoCheck() { this.time = Time.getCurrentTime() }`.
2239

2340
## Forms
2441

@@ -48,6 +65,6 @@ createForm() {
4865

4966
## Dependency Injection
5067

51-
- Use `providedIn: 'root'` for all services which should be available as singletons.
68+
- Use `providedIn: 'root'` for all services, either global or local, which should be available as singletons.
5269
- Use file structure to scope services. A module can only use services that are in its subfoler or share the same parent folder.
5370
- Use `providers: []` for services that 1) need initialization (such as `myService.forRoot()`) or 2) inside `@Component` or `@Directive` for scoped mulitple-instance services.

0 commit comments

Comments
 (0)