Introduction
angularJs is the first edition, angular second edition after collectively.
angular incompatible angularJs.
HttpClient (RxJS reactive programming based)
compared to other frameworks, more suitable for complex applications. High performance, small size.
initialization
Official documents and running quicklynpm install -g @angular/cli
install scaffolding ng new my-app
to create a project cd my-app
to switch to the project ng serve --open
start project
File directory structure
tslint Configuration
tslint.json
Experience Component
Module
Root module
role: Start the application
Module: an independent, closed, by introducing a reference between modules and turned out to complete the
module comprises: components, services, commands, configuration to effect until these
@NgModule
Root component decorator
told angular this class as a module for processing@NgModule{{元数据对象}}
@Component
Component decorator
Data Binding
Interpolation expression
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
// templateUrl: './app.component.html',
template: '<div title="{{company}}">{{title}}--{{company}}--{{1+2}}-- {{fn()}}</div>',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = '塞纳河后台管理'
company = 'snh'
fn () {
return '方法返回内容'
}
}
Binding attribute
attribute binding manner interpolation expression when performing this property will eventually be converted into binding
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
// templateUrl: './app.component.html',
template: `
<a [href]="url">链接</a>
<input type="checkbox" [checked]="isChecked" />
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
url = 'http://www.baidu.com'
isChecked = true
}
Event binding
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
// templateUrl: './app.component.html',
template: `
<button (click)="handleClick()" (mouseenter)="handleMouseEnter()">请点击</button>
<a [href]="url" (click)="handleClick($event)">链接</a>
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
url = 'http://www.baidu.com'
handleClick (event) {
// 阻止浏览器的默认行为
event.preventDefault()
console.log('handleClick', event)
}
handleMouseEnter () {
console.log('handleMouseEnter')
}
}
Two-way data-binding
properties of the combination of binding and binding events
app.module.ts
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
// templateUrl: './app.component.html',
template: `
<input type="text" [(ngModel)]="msg" />
<p>{{msg}}</p>
`,
styleUrls: ['./app.component.scss']
})
export class AppComponent {
msg = '我是默认值'
}
Language Services
instruction
Components: instruction templates have
attributes Instruction: change the appearance and behavior of elements of command
structure type instruction: add and remove DOM elements, change the layout of the instruction DOM
[ngClass]
[ngStyle]
*ngIf
*ngFor
Basic use
Color interlaced
Use trackBy
solve performance problems
common data no performance problems when rendering an object array performance problems when rendering. Then you need to use trackBy
to solve.
todos Case
Communication Components
ng generate component child
Generating a sub-assembly, and the relevant configuration automatically
Pass values to the parent component subassembly
Subassembly to the traditional values parent component
Subassemblies to create an event, a trigger event, passing parameters
Parent component binding events, receive parameters
todos case separate components
ng generate module todos
Create a todos module
target structure is as follows
Specify a location, create three sub-assembliesng generate component todos/todo
ng generate component todos/todo-header
ng generate component todos/todo-list
Root module in the todos
module
Then write the original content in the root module, moved
todos
in to block.
Note:
FormsModule
also moved in the past, otherwise the
todos
module can not be used.
Detached todo-header
components
use to communicate between components, sub-transmission parent - add tasks
Detached todo-list
component
task display, delete, state switches
use to communicate between components from father to son - to get the todos
data
communication between the components to use, the father of the child pass - when you delete and modify the state to modify the parent assembly data, the data source in order to maintain unity
todo
Parent component - provides data agency matters
useTypeScript
angular official recommended ts
enhances the maintainability of the project
is conducive to collaborative development
ts Syntax
- Type of annotation
let id: number
- interface
// 创建接口
interface Todo {
id: number,
name: string,
done: boolean
}
export class TodoComponent implements OnInit {
constructor() { }
// 任务列表
todos: Todo[] = [
{ id: 1, name: '玩游戏啊', done: true },
{ id: 2, name: '点外卖呀', done: false },
{ id: 3, name: '看bilibili', done: false }
]
}
- Generics
@Output()
add = new EventEmitter<string>()
- Class Members modifiers
private todoName: string
Another use interface
service
Component:
providing data binding properties and methods
Services:
business logic, used by components such as access to data from the server, to validate user input, etc.
Component is a consumer services
Service Description:
-
@injectable()
Decorator to indicate a service - To register for the service provider to use
- served by angular dependency injection (DI) to component bit
- DI provides the services you want to use. The need to manually create a service instance
- Recommended for
constructor
use in providing component services
Create and use basic services
ng generate service todos/todos
Generation service
In the todos.service.ts
middle, as a provider of services, there must be@Injectable
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class TodosService {
constructor() { }
// 提供方法
todoTest () {
console.log('test-TodoService')
}
}
Use, todo.component.ts
so that when click Add time, you can call service
// 导入服务
import { TodosService } from '../todos.service'
export class TodoComponent implements OnInit, OnChanges {
constructor(private todoService: TodosService) { }
addTodo(todoName: string) {
// 演示服务的调用
this.todoService.todoTest()
}
ngOnInit() {
}
ngOnChanges() {
}
}
Three ways to register provider
- Root-level providers in all components can be called
@Injectable({
providedIn: 'root'
})
- Within the module provider available
todos.service.ts
@Injectable()
todos.module.ts
// 导入服务
import { TodosService } from './todos.service'
@NgModule({
providers: [
TodosService
]
})
- The available provider components (subcomponents which may be used, Brother assembly can not be used)
todos.service.ts
@Injectable()
todo.component.ts
// 导入服务
import { TodosService } from './../todos.service';
@Component({
providers: [TodosService]
})
export class TodoComponent implements OnInit, OnChanges {
constructor(private todoService: TodosService) { }
addTodo(todoName: string) {
// 演示服务的调用
this.todoService.todoTest()
}
ngOnInit() {
}
ngOnChanges() {
}
}
Case todos modified to use the service
The business logic components pulled into the service
HttpClient
angular is a built-in client, instead of using a third party.
- Role: send http request
- Encapsulates XMLHttpRequest
- Based observable (Observable) object api
- Providing the request and response blocker
- Streaming error handling mechanism
The basic use of HttpClient
app.module.ts
Import
// 导入HttpClient模块
import {HttpClientModule} from '@angular/common/http'
@NgModule({
imports: [
HttpClientModule
],
})
app.component.html
trigger event
<div>
<button (click)="getData()">获取数据</button>
<h3>通过HttpClient获取到的数据是:{{name}}</h3>
</div>
app.component.ts
Interface is used assets
in the json
file simulation
// 导入HttpClient
import { HttpClient } from '@angular/common/http'
export class AppComponent {
constructor(private http: HttpClient) { }
name: string
getData () {
this.http.get('../assets/todos.json').subscribe((res: any) => {
console.log(res)
this.name = res.name
})
}
}
After the addition type checking app.component.ts
, such an approach more rigorous
interface Todo {
name: string,
description: string
}
export class AppComponent {
constructor(private http: HttpClient) { }
name: string
getData () {
this.http.get<Todo>('../assets/todos.json').subscribe((res: Todo) => {
console.log(res)
this.name = res.name
})
}
}
For a complete response
Use { observe: 'response' }
to get a complete response
to use when type checkingHttpResponse
// 导入HttpClient
import { HttpClient, HttpResponse } from '@angular/common/http'
export class AppComponent {
constructor(private http: HttpClient) { }
name: string
getData() {
this.http.get<Todo>('../assets/todos.json', { observe: 'response' })
.subscribe((res: HttpResponse<Todo>) => {
console.log(res)
console.log(res.headers.get('content-type'), res.body)
this.name = res.body.name
})
}
}
Error Handling
getData() {
this.http.get<Todo>('../assets/todos.json1', { observe: 'response' })
.subscribe((res: HttpResponse<Todo>) => {
console.log(res)
console.log(res.headers.get('content-type'), res.body)
this.name = res.body.name
},
err => {
console.log(err)
}
)
}
json-server
json-server official documentationnpm install -g json-server
installation package
new db.json
file, write data inside json
{
"todos": [
{ "id": 1, "name": "玩游戏啊", "done": true },
{ "id": 2, "name": "点外卖啊", "done": false },
{ "id": 3, "name": "看bilibii", "done": false }
]
}
json-server --watch db.json
This is the address of the interface
Other requests
Interface address using the json-server
generated addressapp.component.html
<div>
<button (click)="getData()">get获取</button>
<button (click)="addData()">post增加</button>
<button (click)="delData()">del删除</button>
<button (click)="updateData()">patch修改</button>
</div>
app.component.ts
import { Component } from '@angular/core';
// 导入HttpClient
import { HttpClient } from '@angular/common/http'
interface Todo {
name: string,
description: string
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private http: HttpClient) { }
name: string
url = 'http://localhost:3000/todos'
// get
getData() {
this.http.get(this.url).subscribe(res => {
console.log(res)
})
}
// post
addData() {
this.http.post(this.url,{
name: '测试测试',
done: true
}).subscribe(res => {
console.log('post success:', res)
})
}
// del
delData() {
this.http.delete(`${this.url}/2`).subscribe(res => {
console.log('delete success:', res);
})
}
// patch
updateData() {
this.http.patch(`${this.url}/3`,{
name: '黑呀~我是修改后的数据呀~'
}).subscribe(res => {
console.log('patch success:', res)
})
}
}
todos case HttpClient
routing
Implement SPA (single-page application) infrastructure
correspondence rules URL and components of
angular style using HTML5 (history.pushState) navigation
support: Redirection, routing highlight, wildcards routing, routing parameters, sub-routing, routing module, routing guard, asynchronous routing
The basic use of the route
index.html
<base href="/">
Importing
RouterModule
Configure routing rules
appRoutes
-
Root module configuration
forRoot
Description: The
routing service should be a single case, but in other scenes routing lazy loading will cause the service registered more than once, so useforRoot()
the method to import module, ensure that the project is only oneRouter
service Add export route
<router-outlet></router-outlet>
More routing configuration
New Component
plurality of routing rules can
Default route
{ path: '', redirectTo: '/home', pathMatch: 'full' }
Wildcards routing
It used to match the routing rules not to jump to page 404
// 通配符路由,要放在最后面,不然所有的路由都不能正常匹配
{ path: '**', component: PageNotFoundComponent }`
Programmatic navigation
import { Component, OnInit } from '@angular/core';
// 导入路由提供的服务
import { Router } from '@angular/router'
@Component({
selector: 'app-page-not-found',
templateUrl: './page-not-found.component.html',
styleUrls: ['./page-not-found.component.css']
})
export class PageNotFoundComponent implements OnInit {
// 注入服务
constructor(private router: Router) { }
time = 5
ngOnInit() {
const timerId = setInterval( () => {
this.time--
if (this.time === 0) {
clearInterval(timerId)
// 编程式导航
this.router.navigate(['/home'])
}
}, 1000)
}
}
Routing parameters
ng g c car
Create a new module
with routing rule :id
indicates routing parameters
{
path: 'car/:id',
component: CarComponent
},
app.component.html
Set Jump
<ul>
<li>
<a routerLink="car/1">野马</a>
</li>
<li>
<a routerLink="car/2">法拉利</a>
</li>
<li>
<a routerLink="car/3">兰博基尼</a>
</li>
<li>
<a routerLink="car/4">奇瑞QQ</a>
</li>
</ul>
car.component.ts
In obtaining routing parameters
import { Component, OnInit } from '@angular/core';
// 导入路由服务
import { ActivatedRoute } from '@angular/router'
@Component({
selector: 'app-car',
templateUrl: './car.component.html',
styleUrls: ['./car.component.css']
})
export class CarComponent implements OnInit {
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.route.paramMap.subscribe(param => {
// param中可拿到当前路由跳转的参数
const id = param.get('id')
console.log(param, id);
})
}
}
Sub-routing
New Component
configure routing rules
{
path: 'home',
component: HomeComponent,
children: [{
path: 'home/child',
component: HomeChildComponent
}]
},
Export routes to the child, home.component.html
<p>
home works!
<a routerLink="home/child">子路由</a>
<router-outlet></router-outlet>
</p>
Activate the highlighted route
<!-- 在css中设置actived的样式,即为高亮样式 -->
<!-- [routerLinkActiveOptions]是精确匹配才高亮 -->
<a routerLink='/home' routerLinkActive="actived" [routerLinkActiveOptions]="{exact: true}">首页</a>
<a routerLink='/about' routerLinkActive="actived">关于</a>
Forms
Responsive form
very strong, recommended
model-driven, data-driven view of the idea of
data access synchronization to ensure data and views are consistent, predictable
enhances testability, makes testing simple
built-Form ValidatorTemplate driven form
two-way data binding implementation
vue angular.js
Responsive Form
- Import module responsive Form
import { ReactiveFormsModule } from '@angular/forms';
- Generate and import a new form controls
- Register the control in the template
- Update user name and obtain a user name method
// 获取用户名
getUserName () {
console.log(this.username.value)
}
// 更新用户名
setUserName () {
this.username.setValue('fdd')
}
form validation
- Forms validation is built
inusername.errors
the take values, it is determined by checking whether or not
inusername.dirty
the take value, it is judged whether the entered
<p *ngIf="username.dirty && username.errors?.required">用户名为必填项</p>
In hasError()
the get value, it is determined by checking whether
ngOnInit () {
console.log(this.username)
console.log(this.username.hasError('required'))
}
Checking the plurality of conditions
password = new FormControl('123', [
Validators.required,
Validators.minLength(4)
])
<p *ngIf="password.dirty && password.errors?.minlength">密码格式不正确</p>
- Custom form validator
// 自定义表单验证
nickname = new FormControl('', [this.nicknameValidate])
nicknameValidate(control) {
console.log(control);
if (/^[a-z]{3,6}$/.test(control.value)) {
return null
}
return { error: true }
}
<p *ngIf="nickname.dirty && nickname.hasError('error')">昵称格式不正确</p>
FormGroup
import { Component, OnInit } from '@angular/core';
// 导入表单控件
import { FormControl, Validators, FormGroup } from '@angular/forms';
@Component({
selector: 'app-form-group',
templateUrl: './form-group.component.html',
styleUrls: ['./form-group.component.css']
})
export class FormGroupComponent implements OnInit {
constructor() { }
loginForm = new FormGroup({
username: new FormControl('', Validators.required),
password: new FormControl('123', [
Validators.required,
Validators.minLength(4)
])
});
onSubmit() {
if (this.loginForm.valid) {
console.log('submit');
} else {
console.log('err');
}
}
ngOnInit() {
// console.log(this.loginForm)
}
}
<div>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<label>
<span>用户名:</span>
<input type="text" formControlName="username" />
<span>{{this.loginForm.value.username}}</span>
</label>
<label>
<span>密码:</span>
<input type="text" formControlName="password" />
<span>{{this.loginForm.value.password}}</span>
</label>
<button type="submit">提交</button>
</form>
<p *ngIf="this.loginForm.controls.username.dirty && this.loginForm.controls.username.errors?.required">用户名为必填项</p>
<p *ngIf="this.loginForm.controls.password.dirty && this.loginForm.controls.password.errors?.minlength">密码格式不正确</p>
</div>
FormBuilder
The method of generating a convenient form controls
introduced, injection
loginForm = this.fb.group({
username: ['', Validators.required],
password: ['123', [
Validators.required,
Validators.minLength(4)
]]
});
Reproduced in: https: //www.jianshu.com/p/c360a8134c40