angular study notes - knowledge

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.


13406581-3123b898d3efb7f2.png

initialization

Official documents and running quickly
npm install -g @angular/cli install scaffolding
ng new my-appto create a project
cd my-appto switch to the project
ng serve --openstart project

File directory structure

13406581-c159d7a7627e6e8a.png

13406581-25d0af033277ebde.png
13406581-26fa4b18690dd13e.png

tslint Configuration

tslint.json

Experience Component

13406581-97b275f019fab29c.png

Module

Root module
role: Start the application


13406581-58ce3dc580851a52.png

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{{元数据对象}}

13406581-97a7746c2c971cea.png

@Component

Component decorator


13406581-1ca1e9c14ff01cfe.png

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

13406581-1fd6fb6231426c06.png

app.module.ts
13406581-6c86346e67010b3d.png

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

13406581-973d929c8e827e75.png

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]

13406581-7d3ec2e8f3b245b8.png

[ngStyle]

13406581-d9ff555005a5628e.png

*ngIf

13406581-4b09405f34bbecec.png

*ngFor

Basic use


13406581-5f783bb194513c66.png

Color interlaced


13406581-a314d0590ef81fd8.png

Use trackBysolve performance problems
common data no performance problems when rendering an object array performance problems when rendering. Then you need to use trackByto solve.

13406581-e3fc92dad566cec0.png

todos Case

Communication Components

ng generate component child Generating a sub-assembly, and the relevant configuration automatically

Pass values ​​to the parent component subassembly


13406581-d5a947d96e79a00e.png

13406581-0f0b52e82d81d17c.png

13406581-2ca0cd0aff84c196.png

13406581-30bc2b17562de1a2.png

Subassembly to the traditional values ​​parent component


13406581-5848f2bcbef777f4.png

Subassemblies to create an event, a trigger event, passing parameters


13406581-7a3dd0a0b9b3ee8d.png

13406581-4782985c70896f6e.png

Parent component binding events, receive parameters
13406581-9a8e348a5e1492d0.png

13406581-65b3c6a16ffb6bbf.png

todos case separate components

ng generate module todosCreate a todos module
target structure is as follows

13406581-911634f858588b30.png

Specify a location, create three sub-assemblies
ng generate component todos/todo
ng generate component todos/todo-header
ng generate component todos/todo-list

13406581-77edc6682d383738.png

Root module in the todosmodule

13406581-e20b531e0e44e708.png

13406581-e4fd76b201a28d01.png

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-headercomponents
use to communicate between components, sub-transmission parent - add tasks

Detached todo-listcomponent
task display, delete, state switches
use to communicate between components from father to son - to get the todosdata
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

todoParent component - provides data agency matters

useTypeScript

angular official recommended ts
enhances the maintainability of the project
is conducive to collaborative development

ts Syntax

  1. Type of annotation
let id: number
  1. 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 }
  ]
}
  1. Generics
  @Output()
  add = new EventEmitter<string>()
  1. Class Members modifiers
  private todoName: string

Another use interface


13406581-7798255f08e68e6b.png
13406581-7b3d350a18c46037.png
13406581-5a8a0626c2fdeecc.png

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:

  1. @injectable()Decorator to indicate a service
  2. To register for the service provider to use
  3. served by angular dependency injection (DI) to component bit
  4. DI provides the services you want to use. The need to manually create a service instance
  5. Recommended for constructoruse in providing component services

Create and use basic services

ng generate service todos/todos Generation service

In the todos.service.tsmiddle, 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.tsso 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

  1. Root-level providers in all components can be called
@Injectable({
  providedIn: 'root'
})
  1. Within the module provider available

todos.service.ts

@Injectable()

todos.module.ts

// 导入服务
import { TodosService } from './todos.service'
@NgModule({
  providers: [
    TodosService
  ]
})
  1. 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.tsImport

// 导入HttpClient模块
import {HttpClientModule} from '@angular/common/http'
@NgModule({
  imports: [
    HttpClientModule
  ],
})

app.component.htmltrigger event

<div>
  <button (click)="getData()">获取数据</button>
  <h3>通过HttpClient获取到的数据是:{{name}}</h3>
</div>

app.component.tsInterface is used assetsin the jsonfile 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 documentation
npm install -g json-server installation package
new db.jsonfile, 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

13406581-fe7d1d37edcd1d8a.png

This is the address of the interface

Other requests

Interface address using the json-servergenerated address
app.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

The basic use of the route

  1. index.html
  <base href="/">
  1. ImportingRouterModule

  2. Configure routing rulesappRoutes

  3. Root module configuration

    13406581-862e65f6332cbe2c.png

    forRootDescription: The
    routing service should be a single case, but in other scenes routing lazy loading will cause the service registered more than once, so use forRoot()the method to import module, ensure that the project is only one Routerservice

  4. 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 carCreate a new module
with routing rule :idindicates routing parameters

  { 
    path: 'car/:id', 
    component: CarComponent 
  },

app.component.htmlSet 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.tsIn 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

13406581-95e32802efbf4197.png

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 Validator

  • Template driven form
    two-way data binding implementation
    vue angular.js

Responsive Form

Responsive Form

  1. Import module responsive Form
import { ReactiveFormsModule } from '@angular/forms';
  1. Generate and import a new form controls
  2. Register the control in the template
  3. 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
    in username.errorsthe take values, it is determined by checking whether or not
    in username.dirtythe 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

Guess you like

Origin blog.csdn.net/weixin_34080571/article/details/91212964