内容概要:
- Lifecycle Hooks
- Observable
- Routing
- Forms
- HTTP Request
- Unit Test (Jasmine?)
- Redux
- New Features
- SPA
- Lazy-loading
1. Lifecycle Hooks
Angular offers lifecycle hooks of components and directives for developers to add custom logic. We can implement certain interfaces and implement corresponding hook methods.
按照执行顺序共有8个:
Type | Target |
---|---|
ngOnChanges() | Called after bound input property changes. |
ngOnInit() | Called when the component is initialized. |
ngDoCheck() | Called during every change detection run. |
ngAfterConentInit() | Called after ng-content has been projected into view. |
ngAfterContentChecked() | Called after every time the projected content has been checked. |
ngAfterViewInit() | Called after the component's view and child view have been initialized. |
ngAfterViewCheked() | Called every time the view and child view has been checked. |
ngOnDestroy() | Called before Angular destroys the directive or components. Unsubscribe Observables and detach event handlers to avoid memory leaks. |
What is a view?
Views are basically data structure which consists of view nodes that hold references to corresponding DOM elements. Every component has a component view associated with it.
2. Observable
The Observer pattern is a design pattern in which an object maintains a list of its dependencies, called observers, and notifies them automatically of state changes.
Observables provide support for passing messages between parts of your application. Observables are used for:
- event handling,
- asynchronous programming
- handling multiple values
方法只有被订阅(subscribe)才会被执行
Observables are declarative—that is, you define a function for publishing values, but it is not executed until a consumer subscribes to it. The subscribed consumer then receives notifications until the function completes, or until they unsubscribe.
publisher 创建Observable 实例,其中定义了一个subscribe函数。这个函数只有被 consumer 订阅后才会执行。 订阅者函数用于定义“如何获取或生成那些要发布的值或消息”。
执行Observable, 并接受notifications 需要调用subscribe()方法, 并传入一个observer。subscribe() 调用会返回一个 Subscription 对象,该对象具有一个 unsubscribe() 方法。 当调用该方法时,你就会停止接收通知。
- 定义Observer:
一个observer对象可以对这三个Handlers任意组合。
// Create simple observable that emits three values
const myObservable = of(0,1, 2, 3);
// Create observer object
const myObserver = {
next: x => console.log('Observer got a next value: ' + x),
error: err => console.error('Observer got an error: ' + err),
complete: () => console.log('Observer got a complete notification'),
};
// Execute with the observer object
myObservable.subscribe(myObserver);
// Logs:
// Observer got a next value: 0
// Observer got a next value: 1
// Observer got a next value: 2
// Observer got a next value: 3
// Observer got a complete notification
或者可以让subscribe()方法直接传入回调函数。等同于上一种形式。
myObservable.subscribe(
x => console.log('Observer got a next value: ' + x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
);
Observable 内负责定义如何发送数据(next),何时cancel Observable(error occurs), 何时结束数据发送(complete)
Observer 为监听者, 负责handle接收到的数据或事件(observer第一个参数),如何反馈error(第二个参数),如何反馈complete(第三)
- Operators
可以在Observable发送数据后,observer接收数据前,使用operators对数据进行想要的改动。RxJS定义了一些operators,比如map(), filter(), contact(), flatMap().
可以使用pipe()方法, 将这些operators连接起来,将组合的operators作为参数,并且返回一个新的函数,当执行这个新函数时, 就会顺序执行哪些被组合的operators.
import {map} from 'rxjs/operators';
const operter = myOnservable.pipe(
filter(data => {return data > 0;})
map (data => {return 'Observer got a next value: '+ data;}
));
operter.subscribe(
x => console.log(x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
);
// Logs:
// Observer got a next value: 1
// Observer got a next value: 2
// Observer got a next value: 3
// Observer got a complete notification
- Some Onservable creation function:
import { from } from 'rxjs';
import { interval } from 'rxjs';
import { fromEvent } from 'rxjs';
import { ajax } from 'rxjs/ajax';
// Create an Observable out of a promise
const data = from(fetch('/api/endpoint'));
// Create an Observable that will publish a value on an interval
const secondsCounter = interval(1000);
// Create an Observable that will publish mouse movements
const mouseMoves = fromEvent(el, 'mousemove');
// Create an Observable that will create an AJAX request
const apiData = ajax('/api/data');
- Use Observable to handle common async operations
1.Define custom events that send Observable output data from a child component to a parent component.
- The HTTP module uses observable to handle AJAX requests and respond.
- Router and Forms modules use observables to listen for and respond to the user-input events.
3. Routing
How to set up?
- Generate a RoutingModule, which holds an array of Route type:
ng generate module app-routing --flat --module=app
--flat puts the file in src/app instead of its own folder.
--module=app tells the CLI to register it in the imports array of the AppModule.
//app-routing.module.ts
import {RouterModule, Routes} from '@angular/router';
const routes: Routes = [
{
path : '...',
component: ...
},
...
]
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
- Import the RouterModule and the Routing module in app.module.ts.
import {RouterModule} from '@angular/router';
import {AppRoutingModule} from './app-routing.module';
imports: [
RouterModule,
AppRoutingModule
]
- In the corresponding template, use the URL you defined as a path in the routing module.
Usedirective as a placeholder, corresponding content will be rendered at this place.
- Forms
- Template Driven Form
Need to configure the HTML template. For each element, we need to define name attribute and data-binding with ngModel.
- Reactive Form
Need to import ReactiveFormModule and create FormGroup and FormControll instance in the component class.
详细参见笔记: Angular Form
- Http Request
- Enable HTTP service
HttpClient is Angular's mechanism which performs HTTP request.
We need to configure to make httpClient available everywhere in our app.
import { HttpClientModule } from '@angular/common/http';
@NgModule({
imports: [
HttpClientModule,
],
})
通常,开发者将与server request相关的方法(比如 get,post,put,delete)写在一个单独的service中。在需要调用时,不同的component class会注入此service,并调用它们所需要的方法。
例子: 在 employee.service.ts中:
import {HttpClient} from '@angular/common/http';
constructor(private http: HttpClient) { }
//Get employee data from the server.
GetEmployee(): Observable{
return this.http.get(this.API_URL + '/employee', {withCredentials: true})
.pipe(tap((res) => {
return res;
}));
}
AddEmployee(formValue: object): Observable{
return this.http.post(this.API_URL + '/addEmployee', formValue)
.pipe(res => {
return res;
});
}
DeleteEmployee(id: any): Observable<{ }> {
return this.http.delete(this.API_URL + '/delEmployee/' + id)
.pipe();
}
UpdateEmployee(id: any, formValue): Observable{
return this.http.put(this.API_URL + '/updateEmployee/' + id, formValue)
.pipe(res => {
return res;
});
}
所有的 httpClient 方法都只返回 Observable 类型的值。不同的是,httpClient 所返回的 Observable 只会将值发送一次,之后便结束了。
在使用get来的数据时,需要subscribe它。在employee.component.ts中:
import {EmployeeService} from '../service/employee.service';
constructor(private employeeService: EmployeeService, public dialog: MatDialog) {}
loadEmployee(): void{
this.employeeService.GetEmployee().subscribe(res => {
this.employees = res;
});
}
- HTTP Interceptor
Interceptors are a unique type of Angular Service that we can implement. Interceptors allow us to intercept incoming or outgoing HTTP requests using the
HttpClient
. By intercepting the HTTP request, we can modify or change the value of the request.To create an Interceptor, we need to implement the
HttpInterceptor
interface from@angular/common/http
package. Every time our application makes an HTTP request using theHttpClient
service, the Interceptor calls theintercept()
method.When the
intercept()
method is called Angular passes a reference to the httpRequest object. With this request, we can inspect it and modify it as necessary. Once our logic is completed, we call next.handle and return the updated request onto the application.
- Unit Test (Jasmine?)
A unit test is a way of testing a unit - the smallest piece of code that can be logically isolated in a system. In most programming languages, that is a function, a subroutine, a method, or property.
To test with Karma:ng test
The ng test
command builds the app in watch mode and launches the Karma test runner.
Jasmine: DOM-less simple JavaScript testing framework. It does not rely on browsers, DOM, or any JavaScript framework. Thus it's suited for websites, Node.js projects, or anywhere that JavaScript can run. People testing with plain Jasmine / Mocha most likely are running all the code with the Node virtual machine.
Karma: Karma is a browser test runner. The idea is that browsers do not have natively a concept of loading tests files, running them, and reporting results. What karma does is (roughly) :
- starting a small webserver to serve "client-side" javascript files to be tested (1)
- also serve the "client-side" javascript files with the tests (or Specs, as they're often called) (2)
- serve a custom web page that will run javascript code for the tests (3)
- start a browser to load this page (4)
- report the results of the test to the server (5)
- karma can then again report the results to text files, the console, anything your CI server likes, etc...
Jasmine can be classified as a tool in the "Javascript Testing Framework" category, while Karma is grouped under "Browser Testing".
- Redux workflow:
First we should create a central store of application state and bind it with components using connect function(HOC). Whenever we want to get or set data, the store should dispatch an action created by the action creator. The action with payload later will be sent to all the reducers. The specific reducer will respond to the action and use payload data to update the state in the store accordingly. Components bound with the state will get changed.
- New Features
Difference between AngularJS and Angular2:
- AngularJS is a front-end framework based on Javascript.
- Angular 2 is built on the 'TypeScript'. Angular 2 is completely different from AngularJS. AngularJS had features like controllers, scope variables, etc. In Angular 2, these features were replaced by components and directives.
New Features of Angular 4:
- Improved *nglf and *ngFor:
In Angular 4, it enables us to use if/else design syntax in the template.- Pipes:
A new title case pipe was introduced in Angular 4. This pipe changes every first letter of every word into an uppercase.- Router:
Instead of params or query params to represent the parameters of a URL, Angular 4 uses ParamMap.- Animation package:
In Angular 4, animations have been pulled from the Angular core and packaged as an individual BrowserAnimationModule.- Upgraded to typescript 2.1
- Email validation change
Angular 5 new Features:
- Internationalized Number, Date, and Currency Pipes
- exportAs can give different names for components / directives.
- new enhanced HttpClient(since 4.3)
- Angular Forms adds updateOn: 'Blur' / 'Submit'
ApplyingupdateOn: 'Blur'
will make the value of a Form Control subject to change with the blur event of a native input element associated with it.
Angular 6 new Features:
- In Angular CLI, we can easily update old packages.
ng add -- install and download new packages in your Angular app.
ng update -- Used to update and upgrade your packages.- Declaring the providers inside the service itself.
Before this update, you had to declare the providers array in app.module.ts
Now you can provide your service inside the supervisor itself by putting theprovidedIn:root
property within the "@injectable" decorator.- Use ng-template instead of template directive
- What is SPA(Single Page Application)? How to implement SPA with Angular?
SPA is an application that is built with a single HTML file and uses AJAX to get data to update the view dynamically. Normally, a SPA will load all necessary code (HTML, Javascript, CSS) at the beginning. we don't have to reload the whole page for every users' actions. Instead, the Javascript will dynamically display the HTML template.
Compared to a traditional website, SPA is more like a native desktop application and provides a better user experience.
We can use routing to implement SPA.
- What is lazy-loading in Angular?
It is a feature that loads NgModules as needed. Lazy loading helps keep the initial bundle size smaller, which in turn helps decrease load times.
- How to implement?
To lazy-load Angular modules, use
loadchildren
in your AppRoutingModule routes configuration.
const routes: Routes = [
{
path: 'items',
loadChildren: () => import('./items/items.module').then(m => m.ItemsModule)
}
];
A normal router:
const routes: Routes = [
{
path : '...',
component: ...
},
...
]