Angular学习总结

一、环境搭建篇

1.准备工作

1.1安装node
安装angular的计算机上面必须安装最新的nodejs–注意安装nodejs稳定版本
1.2选择一个 命令工具, npm, cnpm, yarn ,任选其一

2.安装Angular CLI

2.1安装typescript(可选)

$ npm install -g typescript 

新建项目会局部安装,所以该步骤不必须。
2.2全局安装Angular CLI

$ yarn global add @angular/cli  或者 npm install @angular/cli -g

此步骤会安装最新版Angular CLI,如果需要指定版本可使用

$ npm install @angular/cli@12.2.18 -g

2.3检测是否安装成功

$ ng version 或者 ng v

3.创建Angular项目

3.1新建项目

ng new ng-Demo

3.2启动项目
进入项目文件夹

cd my-app

启动服务

npm start或ng serve

如果我们需要自动打开浏览器,添加–open(或-o)

其它参数参考:
–dry-run: boolean, 默认为 false, 若设置 dry-run 则不会创建任何文件
–verbose: boolean, 默认为 false
–link-cli: boolean, 默认为 false, 自动链接到 @angular/cli 包
–skip-install: boolean, 默认为 false, 表示跳过 npm install
–skip-git: boolean, 默认为 false, 表示该目录不初始化为 git 仓库
–skip-tests: boolean, 默认为 false, 表示不创建 tests 相关文件
–skip-commit: boolean, 默认为 false, 表示不进行初始提交
–directory: string, 用于设置创建的目录名,默认与应用程序的同名
–source-dir: string, 默认为 ‘src’, 用于设置源文件目录的名称
–style: string, 默认为 ‘css’, 用于设置选用的样式语法 (‘css’, ‘less’ or ‘scss’)
–prefix: string, 默认为 ‘app’, 用于设置创建新组件时,组件选择器使用的前缀
–mobile: boolean, 默认为 false,表示是否生成 Progressive Web App 应用程序
–routing: boolean, 默认为 false, 表示新增带有路由信息的模块,并添加到根模块中
–inline-style: boolean, 默认为 false, 表示当创建新的应用程序时,使用内联样式
–inline-template: boolean, 默认为 false, 表示当创建新的应用程序时,使用内联模板

4.简单使用

4.1创建组件

ng generate component news(简写:ng g component news)

4.2其他命令
Angualr CLI提供了许多常用命令供我们选择:

ng generate class my-new-class              // 新建类,  新建一个名为my-new-class的类 (class)
ng generate component my-new-component      // 新建组件
ng generate directive my-new-directive      // 新建指令
ng generate enum my-new-enum                // 新建枚举
ng generate module my-new-module            // 新建模块
ng generate pipe my-new-pipe                // 新建管道
ng generate service my-new-service          // 新建服务

当然选择。。简写:

ng g cl my-new-class        // 新建 class
ng g c my-new-component     // 新建组件
ng g d my-new-directive     // 新建指令
ng g e my-new-enum          // 新建枚举
ng g m my-new-module        // 新建模块
ng g p my-new-pipe          // 新建管道
ng g s my-new-service       // 新建服务

二、基础语法篇

1.绑定数据

1.1文本绑定

<h2>{{title}}</h2>
<h3>{{titlename}}</h3>

1.2属性绑定

<!-- 绑定属性 -->
<div [title]="title">{{message}}</div>

1.3Html绑定

<!-- 解析html -->
<span [innerHTML]="content"></span>

2.数据循环 *ngFor

2.1普通循环

<!-- 循环 -->
<ul>
  <li *ngFor="let item of list">{{item}}</li>
</ul>

2.1循环设置key

<!-- 循环 -->
<ul>
  <li *ngFor="let item of list;let key = index">{{key}}--{{item}}</li>
</ul>

3.条件判断*ngIf *ngSwitch

3.1*ngIf

<!-- 条件判断语句ngIf -->
<h1 *ngIf="flag">我是true</h1>
<h1 *ngIf="!flag">我是false</h1>

3.2*ngSwitch

<!-- 条件判断语句ngSwitch -->
<div [ngSwitch]="orderStatus">
<div *ngSwitchCase="1">已经支付</div>
<div *ngSwitchCase="2">已发货</div>
<div *ngSwitchCase="3">已签收</div>
<div *ngSwitchCase="4">已完成</div>
</div>

4.属性绑定 ngClass ngStyle

4.1ngClass

<!-- 属性[ngClass] -->
<div [class]="{'blue':true,'red':false}">class绑定</div>

4.2ngStyle

<!-- 绑定行内样式 -->
<div [ngStyle]="{color:'red'}">我是行内样式</div>

5.管道

<!-- 管道 -->
<div>{{today | date:'YYYY-MM-dd hh:mm:ss'}}</div>

6.执行事件

6.1click

<!-- 点击事件 -->
<button (click)="run($event)">按钮</button>

6.2keydown

<!-- 鼠标按下事件 -->
<input type="text" (keydown)="keyDown($event)">

7.双向数据绑定–MVVM 只是针对表单

7.1 在app.module.ts导入FormsModule
7.2 并在imports导入

 import { FormsModule } from '@angular/forms'; 
 ....
 imports: [  /*配置当前模块运行依赖的其他模块*/
    FormsModule
  ],

7.3在页面中使用

<!-- 双向绑定 -->
<h1 >{{message}}</h1>
<button (click)="setmessage()">改变</button>
<input type="text"  [(ngModel)]="message" />

8.home.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
  title: string = 'ngDemo';
  message: any = '我是home组件'
  today: any = new Date();
  constructor() { }
  // 生命周期
  ngOnInit(): void {
  }
  // HTML内容
  public content = '<h2>我是一个h2标签</h2>'
  // 数组
  public list: any[] = ['苹果', '香蕉', '西瓜']
  // 图片地址
  public picUrl: string = 'https://tse3-mm.cn.bing.net/th/id/OIP-C.e_x8-Ry-rp2r6PHr-ZSSVgHaEK?w=291&h=180&c=7&r=0&o=5&dpr=1.3&pid=1.7'
  // 判断条件
  public flag: boolean = true
  // 订单状态
  public orderStatus: number = 3
  // 事件
  run(event: any) {
    var target = event.target
    console.log(target);
    this.flag = !this.flag
  }
  keyDown(event: any) {
    if (event.keyCode === 13) {
      console.log('你按下了回车键');
      console.log(event.target.value);
    }
  }
  setmessage() {
    console.log(this.message);

  this.message = '改变后'
  }

}

三、组件通信篇

1.原生js进行DOM操作

组件HTML:

<div class="content">

    <p>内容区域</p>

    <div id="box">
          this is box
    </div>
    <br>
    <div id="box1" *ngIf="flag">
      this is box1  
    </div>

    <button (click)="showAside()">弹出侧边栏</button>
    <button (click)="hideAside()">隐藏侧边栏</button>
  </div>
  
  <aside id="aside">
    这是一个侧边栏
  </aside>

组件ts:

public flag:boolean=true;
  constructor() { }

  ngOnInit(): void {
      //组件和指令初始化完成   并不是真正的dom加载完成
      let oBox:any=document.getElementById('box');
      console.log(oBox.innerHTML);
      oBox.style.color="red";
      //获取不到dom节点
     /*
      let oBox1:any=document.getElementById('box1');
      console.log(oBox1.innerHTML);
      oBox1.style.color="blue";
     
     */
  }
     //视图加载完成以后触发的方法    dom加载完成  (建议把dom操作放在这个里面)  
    ngAfterViewInit(){
        let oBox1:any=document.getElementById('box1');
        console.log(oBox1.innerHTML);
        oBox1.style.color="blue";
    }

  showAside(){
    //原生js获取dom节点
    var asideDom:any=document.getElementById('aside');
    asideDom.style.transform="translate(0,0)";

 }

hideAside(){
   //原生js获取dom节点
   var asideDom:any=document.getElementById('aside');
   asideDom.style.transform="translate(100%,0)";

}

2.Angular中进行DOM操作

2.1组件模版定义属性(使用#)

<div #ngbox>我是ngbox</div>

2.2组件ts通过ViewChild 获取dom
在这里插入图片描述

3.父组件获取子组件的数据和方法

父组件:news
子组件:header
3.1在父组件中调用子组件并使用#定义一个名称

<app-header #header ></app-header>

3.2在父组件引入ViewChild

import { Component, OnInit,ViewChild } from '@angular/core';

3.3利用属性装饰器ViewChild 和刚才的子组件关联起来

  @ViewChild('header')
  public header: any;

3.4调用子组件

  getChildProp() {
    console.log(this.header);
  }

3.5news.component.ts

import { Component, OnInit,ViewChild } from '@angular/core';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.scss']
})
export class NewsComponent implements OnInit {
  @ViewChild('ngbox')
  public ngbox: any;
  @ViewChild('header')
  public header: any;
  constructor() { }
  title: any = '我是新闻'

  ngOnInit(): void {
  console.log("ngbox",this.ngbox);
  }
  ngAfterViewInit(): void {
    console.log("ngbox",this.ngbox);
  }
  getChildProp() {
    console.log(this.header);
  }
}

4.父组件给子组件传值

父组件:news
子组件:header
4.1父组件调用子组件的时候传入数据

<app-header  [titlename]="title"></app-header>

4.2子组件引入 Input 模块

import { Component, OnInit ,Input } from '@angular/core';

4.3子组件中 @Input 接收父组件传过来的数据
在这里插入图片描述
4.4子组件中使用父组件的数据

<h3>{{titlename}}</h3>

5.子组件通过@Output触发父组件的方法

5.1子组件引入 Output 和 EventEmitter

   import { Component, OnInit ,Input,Output,EventEmitter} from '@angular/core';

5.2子组件中实例化 EventEmitter

 @Output() public send = new EventEmitter();

5.3子组件通过 EventEmitter 对象 send实例广播数据

  sendName() {
    this.send.emit(this.message)
  }

5.4父组件调用子组件的时候,定义接收事件 ,send就是子组件的 EventEmitter 对象 send

<app-header [hometitle]="title" [homeWork]="homeWork" (send)="send($event)"></app-header>

5.5父组件接收到数据会调用自己的 send方法,这个时候就能拿到子组件的数据

  send(ev:any) {
    console.log(ev);
  }

6.非父子组件通讯

1、公共的服务
2、Localstorage(推荐)
3、Cookie

四、生命周期篇

官方定义:https://angular.cn/guide/lifecycle-hooks

1.ngOnChanges()

当 Angular(重新)设置数据绑定输入属性时响应。 该 方法接受当前和上一属性值的 SimpleChanges 对象 当被绑定的输入属性的值发生变化时调用,首次调用一 定会发生在 ngOnInit() 之前。
当被绑定的输入属性的值发生变化时调用(父子组件传值的时候会触发)

2.ngOnInit()

在 Angular 第一次显示数据绑定和设置指令/组件的输 入属性之后,初始化指令/组件。 在第一轮 ngOnChanges() 完成之后调用,只调用一次。
使用 ngOnInit() 有两个原因:
1、在构造函数之后马上执行复杂的初始化逻辑
2、在 Angular 设置完输入属性之后,对该组件进行准备。 有经验的开发者会认同组件的构建应该很便宜和安全。
请求数据一般放在这个里面

3.ngDoCheck()

检测,并在发生 Angular 无法或不愿意自己检测的变 化时作出反应。在每个 Angular 变更检测周期中调用, ngOnChanges() 和 ngOnInit()之后。
检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应

4.ngAfterContentInit()

当把内容投影进组件之后调用。第一次 ngDoCheck() 之 后调用,只调用一次。
当把内容投影进组件之后调用

5.ngAfterContentChecked()

每次完成被投影组件内容的变更检测之后调用。 ngAfterContentInit() 和每次 ngDoCheck() 之后调用。

6.ngAfterViewInit()

初始化完组件视图及其子视图之后调用。第一次 ngAfterContentChecked()之后调用,只调用一次。
初始化完组件视图及其子视图之后调用(dom操作放在这个里面)

7.ngAfterViewChecked()

每次做完组件视图和子视图的变更检测之后调用。 ngAfterViewInit()和每次 ngAfterContentChecked() 之后 调用

8.ngOnDestroy()

当 Angular 每次销毁指令/组件之前调用并清扫。在这 儿反订阅可观察对象和分离事件处理器,以防内存泄 漏。 在 Angular 销毁指令/组件之前调用。

五、异步请求篇

演示组件:ngdemo\src\app\async\http
演示服务: ngdemo\src\app\services\request.service.ts

1.Angular get 请求数据

1.1在 app.module.ts 中引入 HttpClientModule 并注入

import {HttpClientModule} from '@angular/common/http'

imports: [ BrowserModule, HttpClientModule ]

1.2在用到的地方引入 HttpClient 并在构造函数声明

import {HttpClient} from "@angular/common/http";
constructor(public http:HttpClient) { }

1.3get 请求数据

var api = "http://localhost:3000/info";
this.http.get(api).subscribe(response => {
console.log(response);
});

1.4http.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
// const Qs = require('qs');
import Qs from 'qs';

@Component({
  selector: 'app-http',
  templateUrl: './http.component.html',
  styleUrls: ['./http.component.less']
})
export class HttpComponent implements OnInit {

  constructor(public http: HttpClient) { }

  ngOnInit(): void {
    this.getGetdata();
    // this.getPostdata()
  }
  getGetdata() {
    var parmas = { username: 'admin' }
    var newparmas = Qs.stringify(parmas)
    console.log(newparmas);

    // 方法1
    // this.http.get(' http://localhost:3000/users?username=admin').subscribe((response) => {
    //   console.log(response);
    // })
    // 方法2
    // this.http.get(' http://localhost:3000/users?' + newparmas).subscribe((response) => {
    //   console.log(response);
    // })
    // 方法3
    // var newparmas2 = new HttpParams({ fromString: newparmas })
    // this.http.get(' http://localhost:3000/users', {
    //   params:newparmas2
    // }).subscribe((response) => {
    //   console.log(response);
    // })

  }
  // getPostdata() {
  //   this.http.post(' http://localhost:3000/users',{name:'小刘'},{new Httpheaders:{'Content-Type':'application/json'}}).subscribe((response) => {
  //     console.log(response);
  //   })
  // }

}

2. Angular post 提交数据

Angular5.x 以后 get、post 和和服务器交互使用的是 HttpClientModule 模块。

1、在 app.module.ts 中引入 HttpClientModule 并注入

import {HttpClientModule} from ‘@angular/common/http’;
imports: [ BrowserModule, HttpClientModule ]

2、在用到的地方引入 HttpClient、HttpHeaders 并在构造函数声明 HttpClient
import {HttpClient,HttpHeaders} from “@angular/common/http”;
constructor(public http:HttpClient) { }

3.post 提交数据

const httpOptions={
headers:newHttpHeaders({‘Content-Type’:‘application/json’})
};
var api=“http://127.0.0.1:3000/doLogin”;
this.http.post(api,{username:‘张三’,age:‘20’},httpOptions).subscribe(response=>{
console.log(response);
});

3. Angular 中使用第三方模块 axios 请求数据

1.安装 axios
yarn add axios -D

2、用到的地方引入 axios
import axios from ‘axios’;

3、看文档使用

axios.get('/user?ID=12345') 
.then(function(response){ 
  //handle success 
  console.log(response); 
  }) 
.catch(function(error){ 
  //handle error
    console.log(error); 
  }) 
.then(function(){ 
  //always executed 
  });

4.封装Rxjs

1.rxjs.service.ts

import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { environment } from 'src/environments/environment'; import Qs from 'qs'

@Injectable({   providedIn: 'root' }) export class RxjsService {

  constructor(public http:HttpClient) { }   getFun(url: string, data: any) {
    var params = Qs.stringify(data);
    return this.http.get(environment.baseURL + url + "?" + params);   }   postFun(url: string, data: any) {
    return this.http.post(environment.baseURL + url, data, {
      headers:new HttpHeaders ({
        'Content-Type': 'application/json' // 默认值
    })})   } }

5.封装axios

1.下载axios
npm i axios
2.axios.service.ts

import { Injectable } from '@angular/core';
import axios from 'axios';
import Qs from 'qs'

axios.defaults.timeout = 5000
import { environment } from 'src/environments/environment';
console.log(environment.baseURL,'base');
// 请求基础路径
axios.defaults.baseURL = environment.baseURL
//http request 拦截器  客户端给服务端 的数据
axios.interceptors.request.use(
  config => {

    config.headers.common = {
      'X-API-TOKEN': localStorage.getItem('token'),
      'version': '1.0',
      'Content-Type': 'application/json;charset=UTF-8'
    }

    if (config.data && config.data.form) {
      //转化成formData格式
      // transformRequest只能用在 PUT, POST, PATCH 这几个请求方法
      config.transformRequest = [function (data) {
        //方式一
        delete data.form;
        // var ret = '';
        // for (let it in data) {
        //   ret += it+'=' +data[it] + '&';
        // }
        // return ret.substring(0,ret.length-1);

        //方式二:
        var test2 = Qs.stringify(data);
        return test2;
      }]
    }

    return config;
  },
  error => {
    return Promise.reject();
  }
);

//响应拦截器即异常处理 -  -- 服务给客户端的数据进行处理
axios.interceptors.response.use(response => {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response);
  } else {
    return Promise.reject(response);
  }
  // return response
}, err => {
  if (err && err.response) {
    var errorMsg = '';
    switch (err.response.status) {
      case 400:
        console.log('错误请求')
        errorMsg = '错误请求';
        break;
      case 401:
        console.log('未授权,请重新登录');
        errorMsg = '未授权,请重新登录';
        break;
      case 403:
        console.log('拒绝访问')
        errorMsg = '拒绝访问';
        break;
      case 404:
        console.log('请求错误,未找到该资源')
        errorMsg = '请求错误,未找到该资源';
        break;
      case 405:
        console.log('请求方法未允许')
        errorMsg = '请求方法未允许';
        break;
      case 408:
        console.log('请求超时')
        errorMsg = '请求超时';
        break;
      case 500:
        console.log('服务器端出错')
        errorMsg = '服务器端出错';
        break;
      case 501:
        console.log('网络未实现')
        errorMsg = '请求方法未允许';
        break;
      case 502:
        console.log('网络错误')
        errorMsg = '网络错误';
        break;
      case 503:
        console.log('服务不可用')
        errorMsg = '服务不可用';
        break;
      case 504:
        console.log('网络超时')
        errorMsg = '网络超时';
        break;
      case 505:
        console.log('http版本不支持该请求')
        errorMsg = 'http版本不支持该请求';
        break;
      default:
        console.log(`连接错误${err.response.status}`)
    }

    alert(errorMsg);

  } else {
    console.log('连接到服务器失败')
  }
  return Promise.resolve(err.response)
})


@Injectable({
  providedIn: 'root'
})
export class AxiosService {

  constructor() { }
  //  包装一个 直接利用axios自身是一个Promise对象的思想封装
  postFun(url: string, data: any) {
    return new Promise((resolve, reject) => {
      axios.post(url, data)
        .then(response => {
          resolve(response);
        })

    })
  }

  getFun(url: string, params = {}) {

    return new Promise((resolve, reject) => {
      axios.get(url, {
        params: params
      })
        .then(response => {
          resolve(response.data);
        })

    })
  }
}

六、路由配置篇

1.配置默认路由

<a routerLink="/home">首页</a>
<a routerLink="/news">新闻</a>
//匹配不到路由的时候加载的组件 或者跳转的路由
{
    path: '**', /*任意的路由*/
    // component:HomeComponent
    redirectTo:'home'
}

2.Angular routerLinkActive 设置 routerLink 默认选中路由

方法一:

<h1>
  <a routerLink="/home" routerLinkActive="active">
    首页
  </a>
  <a routerLink="/news" routerLinkActive="active">
    新闻
  </a>
</h1>

方法二:

<h1>
    <a [routerLink]="[ '/home' ]" routerLinkActive="active">首页</a>
    <a [routerLink]="[ '/news' ]" routerLinkActive="active">新闻</a>
</h1>

3.动态路由

1.问号传参
问号传参的url地址显示为 …/list-item?id=1
方法一:

<a [routerLink]="['/list-item']" [queryParams]="{id:item.id}">
<span>{{ item.name }}</span>
</a>

方法二:

import { Router } from '@angular/router';

constructor(private router: Router) {}

this.router.navigate(['/newscontent'],{
  queryParams:{
    name:'laney',
    id:id
  },
  skipLocationChange: true 
  //可以不写,默认为false,设为true时路由跳转浏览器中的url会保持不变,传入的参数依然有效
});

获取参数:

import { ActivatedRoute } from '@angular/router';

constructor(public route:ActivatedRoute) { }
ngOnInit() { 
    this.route.queryParams.subscribe((data)=>{
      console.log(data);
 })
}

2.路径传参
路径传参的url地址显示为 …/list-item/1
方法一:

<a [routerLink]="['/list-item', item.id]">
  <span>{{ item.name }}</span>
</a>

方法二:

this.router.navigate(['/list-item', item.id]);

路径配置:
{path: 'list-item/:id', component: ListItemComponent}

获取参数方式:

this.route.params.subscribe(
  param => {
      this.id= param['id'];
  }
)

4.父子路由

1.创建组件引入组件

import { WelcomeComponent } from './components/home/welcome/welcome.component';
import { SettingComponent } from './components/home/setting/setting.component';

2.配置路由

{
    path:'home',
    component:HomeComponent,
    children:[{
      path:'welcome',
      component:WelcomeComponent
    },{
      path:'setting',
      component:SettingComponent
    },
    {path: '**', redirectTo: 'welcome'}
  ]
},

3.父组件中定义router-outlet

<router-outlet></router-outlet>
  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值