Angular基础学习(入门 --> 入坑)

目录

[一、Angular 环境搭建](#一、Angular 环境搭建)

二、创建Angular新项目

三、数据绑定

四、ngFor循环、ngIf、ngSwitch、[ngClass]、[ngStyle]、管道、事件、双向数据绑定--MVVM

[五、DOM 操作 (ViewChild)](#五、DOM 操作 (ViewChild))

六、组件通讯

七、生命周期

[八、Rxjs 异步数据流](#八、Rxjs 异步数据流)

[九、Http 请求](#九、Http 请求)

[十、使用axios 请求数据](#十、使用axios 请求数据)

十一、路由

[十二、动态路由 & get 传值](#十二、动态路由 & get 传值)

[十三、动态路由的 js 跳转路由](#十三、动态路由的 js 跳转路由)

十四、父子路由(嵌套路由)

十五、vdemo项目


一、Angular 环境搭建

1、安装nodejs,通过node -v查看node版本安装是否成功(自行百度安装)

2、安装npm / yarn / cnpm /pnpm,npm -v查看npm版本是否成功(自行百度安装)

3、npm install -g @angular/cli@7.0.6(学习的版本稳定)

4、ng v 验证安装是否成功

二、创建Angular新项目

1、使用命令创建

ng new vdemo

2、配置选项(1、是否使用路由 【暂时不用N】,2、会哪个选那个,上下选择,回车就会创建好项目,并且下载好依赖)

npm new vdemo --skip-install -- 创建项目不下载依赖 -- 后面 自行执行 npm i

也可以自行到目录下执行npm i 下载依赖

3、项目启动

ng serve --open

4、angular6 中使用socket.io报global is not defined 错误如何解决

angular6 中使用socket.io报global is not defined 错误如何解决

5、目录介绍

6、自定义组件命令

https://angular.dev/cli

ng g 查看模块

ng g component components/news 创建组件

在根组件引入news组件

效果:

三、数据绑定

<----! html ------->

html 复制代码
<h1>angular模板里面绑定数据</h1>
<p>
  {{ title }}
</p>

<p>{{ msg }}</p>

<p>{{ username }}</p>
<p>{{ student }}</p>
<p>{{ userInfo.username }}、{{ userInfo.age }}</p>
<p>{{ message }}</p>

<hr />
<!-- ----------------------------------------------------------------- -->

<h1>angular模板里面绑定属性</h1>
<div title="我是一个属性">宇哥很帅</div>

<br />

<div [title]="student">宇哥很帅-lalal</div>

<hr />

<!-- ----------------------------------------------------------------- -->
<h1>angular模板里面绑定html</h1>

<div>{{ content }}</div>
<!-- 解析html -->
<div [innerHTML]="content" class="red"></div>
<hr>
<!-- ----------------------------------------------------------------- -->

<h1>angular模板里面允许做简单的运算</h1>
1+2={{ 1 + 2 }}
<hr>
<!-- ----------------------------------------------------------------- -->
<h1>angular模板里面数据循环</h1>
<br />

<ul>
  <li *ngFor="let item of arr">{{ item }}</li>
</ul>

<br />

<ul>
  <li *ngFor="let item2 of list">{{ item2 }}</li>
</ul>
<br />

<ul>
  <li *ngFor="let item3 of items">{{ item3 }}</li>
</ul>

<br />
<ul>
  <li *ngFor="let item4 of listList">{{ item4.name }}、{{ item4.age }}</li>
</ul>

<br />
<ul>
  <li *ngFor="let item5 of cars">
    <h2>{{ item5.name }}</h2>
    <ol>
      <li *ngFor="let its of item5.list">{{ its.name }} --- {{ its.price }}</li>
    </ol>
  </li>
</ul>

<----! ts ------->

javascript 复制代码
import { Component, OnInit } from "@angular/core";

@Component({
  selector: "app-news",
  templateUrl: "./news.component.html",
  styleUrls: ["./news.component.css"],
})
export class NewsComponent implements OnInit {
  // 声明属性的几种方法
  // public  共有(默认) 可以在这个类里面使用、也可以在类外面使用
  // protected  保护类型  它只有在当前类和它的子类里面访问
  // private   私有   当前类才可以访问这个属性只有在
  
  public title = "我是新闻组件";

  msg = "我是新闻组件中的msg";

  private username = "张三";

  // 推荐
  public student: any = "我是一个学生";

  public userInfo: object = {
    username: "张三",
    age: "20",
  };

  public message: any;

  public content="<h2>我是新闻组件中的content</h2>";

  // 定义数组
  public arr=['111','222','333']
  // 推荐
  public list:any[] = ['我是第一个',222222,'443425']
  public items:Array<string>=['第一个新闻','第二个新闻']
  
  // 复杂数组
  public listList:any[]=[
    {
      id:1,
      name:'张三',
      age:20
    },
    {
      id:2,
      name:'李四',
      age:22
    },
    {
      id:3,
      name:'王五',
      age:23
    }
  ]

  public cars:any[]=[
    {
      name:'宝马',
      list:[
        {
          name:'宝马X1',
          price:'30W'
        },
        {
          name:'宝马X2',
          price:'20W'
        }
      ]
      
    },
    {
      name:'奥迪',
      list:[
        {
          name:'奥迪Q1',
          price:'130W'
        },
        {
          name:'奥迪Q2',
          price:'1120W'
        }
      ]
      
    }
  ]

  constructor() {
    this.message = "这是给属性赋值--(改变属性的值)";

    this.msg = "我是新闻组件中的msg==(我是改变后的值)";
  }

  ngOnInit() {}
}

效果:

四、*ngFor循环、*ngIf、ngSwitch、[ngClass]、[ngStyle]、管道、事件、双向数据绑定--MVVM

<----! html ------->

html 复制代码
<h1>引入图片</h1>

<img style="width: 300px; height: 300px" src="assets/images/1.jpg" alt="" />
<hr />

<img style="width: 300px; height: 300px" [src]="picUrl" alt="" />
<hr />

<h1>循环数据 显示数据的索引(key)</h1>
<ul>
  <li *ngFor="let item of list; let key = index">
    {{ key }}--{{ item.title }}
  </li>
</ul>

<hr />

<h1>条件判断语句 *ngIf</h1>
<div *ngIf="flag">
  <img style="width: 300px; height: 300px" src="assets/images/1.jpg" alt="" />
</div>
<div *ngIf="!flag">
  <img style="width: 300px; height: 300px" [src]="picUrl" alt="" />
</div>

<hr>
<ul>
  <li *ngFor="let item of list; let key = index">
    <span *ngIf="key == 1" class="reds">{{ key }}--{{ item.title }}</span>
    <span *ngIf="key != 1">{{ key }}--{{ item.title }}</span>
  </li>
</ul>
<hr>

<h1>条件判断语句 *ngSwitch</h1>
<ul [ngSwitch]="orderStatus">
  <li *ngSwitchCase="1">下单</li>
  <li *ngSwitchCase="2">支付</li>
  <li *ngSwitchCase="3">已支付</li>
  <li *ngSwitchCase="4">已购买</li>
</ul>
<hr>

<h1>属性 [ngClass]、[ngStyle]</h1>
<div class="reds">
  ngClass1111
</div>
<hr>
<div [ngClass]="{'reds': 'true', 'blue': 'false'}">
  ngClass1111
</div>
<hr>
<div [ngClass]="{'orange': 'flag', 'blue': '!flag'}">
  ngClass1111
</div>
<hr>


<h1>循环数组、改变数组某一项的样式</h1>
<ul>
  <li *ngFor="let item of list; let key = index" [ngClass]="{'reds': key == 1, 'blue':key == 2,'orange':key == 3}">
    {{ key }}--{{ item.title }}
  </li>
</ul>
<hr>

<p style="color: aqua;">我是一个p标签</p>
<br>
<p [ngStyle]="{'color':'pink'}">我是一个p标签</p>
<br>
<p [ngStyle]="{'color':attr}">我是一个p标签</p>
<hr>


<h1>管道</h1>
<p> {{ today | date:'yyyy-MM-dd HH:mm ss' }}</p>
<hr>

<h1>事件</h1>
<p>{{title}}</p>
<br>
<button (click)="run()">点击我</button>
<br>
<button (click)="getData()">点击我获取title</button>
<br>
<button (click)="changeData()">点击我改变title</button>
<br>
<button (click)="runEvent($event)">点击我改变颜色</button>
<hr>

<h1>表单事件、事件对象</h1>
keyDown:
<input type="text" (keydown)="keyDown($event)" />
<br>
keyUp:
<input type="text" (keydown)="keyUp($event)" />
<hr>

<h1>双向数据绑定--MVVM</h1>
<input type="text" [(ngModel)]="keywords" />
<p>{{keywords}}</p>
<br>
<button (click)="changeKeywords()">改变keyWords值</button>
<br>
<button (click)="getKeywords()">获取keyWords值</button>

<----! ts ------->

javascript 复制代码
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  public title = '我是标题'

  public keywords = '我是默认值'
  
  public picUrl = 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'
  
  public list:any[] = [
    {
      title: 'title1',
    },
    {
      title: 'title2',
    },
    {
      title: 'title3',
    },
    {
      title: 'title4',
    }
   ]

   public flag:boolean = false;

   public orderStatus:number=1
   
   public attr:string = 'orange'

   public today:Date = new Date()

  constructor() { }

  ngOnInit() {
  }
  run(){
    alert('点击了我-哈哈')
  }
  getData(){
    alert(this.title)
  }

  changeData(){
    this.title = '我是改变后的title'
  }
  runEvent(e){
    let dom:any = e.target
    dom.style.color = 'red'
  }

  // 表单事件
  keyDown(e){
    if(e.keyCode == 13){
      alert('按下回车')
    }else{
      console.log(e.target.value)
    }
  }

  keyUp(e){
    if(e.keyCode == 13){
      console.log(e.target.value)
      alert('keyUp按下回车')
    }
  }
  // 双向数据绑定
  changeKeywords(){
    this.keywords = '我是改变后的值'
  }
  getKeywords(){
    alert(this.keywords)
  }

}

效果:

五、DOM 操作 (ViewChild)

<----! html ------->

html 复制代码
<app-header #header></app-header>

<hr>

<div #myBox>
  xinwen
</div>
<button (click)="getChild()">获取header子组件值</button>

<----! ts ------->

javascript 复制代码
import { Component, OnInit,ViewChild } from '@angular/core';

@Component({
  selector: 'app-news',
  templateUrl: './news.component.html',
  styleUrls: ['./news.component.css']
})
export class NewsComponent implements OnInit {
  
  @ViewChild('myBox') myBox:any
  @ViewChild('header') header:any

  constructor() { }

  ngOnInit() {
  }
  ngAfterViewInit(){
    this.myBox.nativeElement.style.color = 'blue'
  }
  getChild(){
    this.header.run()
  }

}
javascript 复制代码
import { Component, OnInit } from '@angular/core';

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

  constructor() { }

  ngOnInit() {
  }
  run(){
    alert('我是header子组件!!!')
  }

}

原生 js 获取DOM

<----! html ------->

html 复制代码
<h1>DOM 操作</h1>

<div id="box">
  this is box
</div>

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

<----! ts ------->

javascript 复制代码
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  public flag:boolean = true

  constructor() { }

  ngOnInit() {
    let box = document.getElementById("box")
    box.style.color = 'red'

    /*
      使用ngif 获取不到DOM 节点
      let box1 = document.getElementById("box1")
      box1.style.color = 'yellow'
    */ 

    
  };
  // 视图加载完成,获取DOM 节点
  ngAfterViewInit(){
    let box1 = document.getElementById("box1")
    box1.style.color = 'pink'
  }

}

父传子 / 获取一个组件的实例 (ViewChild)

效果图:

六、组件通讯

1、父传子 @input

获取父组件的方法

把整个父组件传给子组件 使用 this

父组件通过@ViewChild主动获取子组件的数据和方法

2、子传父 @Output 、EventEmiter

3、非父子组件的通信(eg:兄弟) todolist里有

3.1、lacalstorage

3.2、service 服务

3.3、Angular文档:https://www.angular.cn/guide/lifecycle-hooks

七、生命周期

<----! lifecycle.component.html ------->

html 复制代码
<h1>{{msg}}</h1>
<hr>
<br>
<button (click)="changeMsg()">改变Msg</button>
<br>
<br>
<input type="text" [(ngModel)]="userinfo">

<----! lifecycle.component.ts ------->

javascript 复制代码
import { Component, OnInit ,Input} from "@angular/core";

@Component({
  selector: "app-lifecycle",
  templateUrl: "./lifecycle.component.html",
  styleUrls: ["./lifecycle.component.css"],
})
export class LifecycleComponent implements OnInit {

  @Input('title2') title2:string;
  

  public msg: string = "我是一个生命周期演示哦";

  public userinfo: string = "";
  public oldUserinfo: string = "";
  constructor() {
    console.log(
      "00构造函数执行了---除了使用简单的值对局部变量进行初始化之外,什么都不应该做"
    );
  }
  ngOnChanges() {
    console.log(
      "01ngOnChanges执行了---当绑定的输入属性的值发生变化时调用 (父子组件传值会触发)"
    );
  }

  ngOnInit() {
    console.log("02ngonInit执行了--- 请求数据一般放在这个里面");
  }
  ngDoCheck() {
    // 写一写自定义操作
    console.log(
      "03ngDocheck执行了---捡测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应"
    );

    if (this.userinfo !== this.oldUserinfo) {
      console.log(`你从${this.oldUserinfo}改成${this.userinfo}`);
      this.oldUserinfo = this.userinfo;
    } else {
      console.log("数据没有变化");
    }
  }

  ngAfterContentInit() {
    console.log("04ngAftercontentInit执行了---当把内容投影进组件之后调用");
  }
  ngAfterContentChecked() {
    console.log(
      "05ngAftercontentchecked执行了---每次完成被投影组件内容的变更检测之后调用"
    );
  }
  ngAfterViewInit() {
    console.log(
      "06 ngAfterViewInit执行了----初始化完组件视图及其子视图之后调用(dom操作放在这个里面"
    );
  }
  ngAfterViewChecked() {
    console.log(
      "07ngAfterViewchecked执行了----每次做完组件视图和子视图的变更检测之后调用"
    );
  }
  ngOnDestroy() {
    console.log("08ngonDestroy执行了...");
  }

  changeMsg() {
    this.msg = "我是一个生命周期演示哦-- 我变了";
  }
}

效果图:

改变值触发哪些函数:如下

javascript 复制代码
<button (click)="changeMsg()">改变Msg</button>

销毁组件

八、Rxjs 异步数据流

中文手册:​​​​​https://cn.rx.js.org/

1、创建服务:ng g service services/request

2、引入服务

异步编程:

<----! request.service.ts ------->

javascript 复制代码
import { Injectable } from "@angular/core";

import { Observable } from "rxjs";

@Injectable({
  providedIn: "root",
})
export class RequestService {
  constructor() {}
  // 同步
  getData() {
    return "this is service data";
  }
  // 异步
  getCallbackData(cb) {
    setTimeout(() => {
      var username = "zhangsan";
      // return username
      cb(username);
    }, 1000);
  }
  // promise异步
  getPromiseData() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        var username = "zhangsan---promise";
        resolve(username);
      }, 2000);
    });
  }
  // Rsjx异步
  getRsjxData() {
    return new Observable((observer) => {
      setTimeout(() => {
        var username = "zhangsan---Rsjx异步";
        observer.next(username)
        // observer.error('错误数据')
      }, 2000);
    });
  }

  // 多次执行
  getPromisSeintervaleData() {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        var username = "zhangsan---promise多次执行";
        resolve(username);
      }, 1000);
    });
  }
  getRxjsSeintervaleData() {
    let count = 0
    return new Observable<any>((observer) => {
      setInterval(() => {
        count++;
        var username = "zhangsan---Rsjx多次执行";
        observer.next(username)
        // observer.error('错误数据')
      }, 1000);
    });
  }

  getRxjsintervaleNum() {
    let count = 0
    return new Observable<any>((observer) => {
      setInterval(() => {
        count++;
        observer.next(count)
        // observer.error('错误数据')
      }, 1000);
    });
  }
}

<----! home.component.ts ------->

javascript 复制代码
import { Component, OnInit } from "@angular/core";
import { RequestService } from "../../services/request.service";

import { filter, map } from "rxjs/operators";

@Component({
  selector: "app-home",
  templateUrl: "./home.component.html",
  styleUrls: ["./home.component.css"],
})
export class HomeComponent implements OnInit {
  constructor(public request: RequestService) {}

  ngOnInit() {
    // 1、同步方法
    let data = this.request.getData();
    console.log(data);

    // 2、获取异步方法&数据
    this.request.getCallbackData((data) => {
      console.log(data);
    });

    // 3、promise异步
    var promiseData = this.request.getPromiseData();
    promiseData.then((data) => {
      console.log(data);
    });
    // 4、rxjs获取异步方法数据
    // var rxjsData = this.request.getRsjxData();
    // rxjsData.subscribe((data) => {
    //   console.log(data);
    // });

    // 5、rxjs unsubscribe取消订阅
    var streem = this.request.getRsjxData();
    var d = streem.subscribe((data) => {
      console.log(data);
    });
    setTimeout(() => {
      d.unsubscribe(); /* 取消订阅 */
    }, 1000);

    // 6、promise 执行多次(没有这个能力)
    var intervalData = this.request.getPromisSeintervaleData();
    intervalData.then((data) => {
      console.log(data);
    });

    // 7、Rxjs执行多次
    // var streemInterval = this.request.getRxjsSeintervaleData();
    // streemInterval.subscribe((data) => {
    //   console.log(data);
    // });

    // 8、用工具方法对返回数据进行处理
    /*
   
    //  filter
    var streemNum = this.request.getRxjsintervaleNum();
    streemNum.pipe(
      filter((value) => {
        if(value%2==0){
          return true
        }
      }),
    )
    .subscribe((data) => {
      console.log(data);
    });
   
   */

    /*
      // map
      var streemNum = this.request.getRxjsintervaleNum();
      streemNum.pipe(
        map((value) => {
        return value*value
        }),
      )
      .subscribe((data) => {
        console.log(data);
      });
    */

      // fliter & map 的结合使用
      var streemNum = this.request.getRxjsintervaleNum();
      streemNum.pipe(
        filter((value) => {
          if(value%2==0){
            return true
          }
        }),
        map((value) => {
          return value*value
        }),
      )
      .subscribe((data) => {
        console.log(data);
      });
  }
}

九、Http 请求

1、get 请求数据

2、post提交数据

3、jsonp 请求数据

十、使用axios 请求数据

asiox : https://github.com/axios/axios

1、创建服务

ng g service services/httpservice

2、安装:asiox

npm i axios --save

3、在服务中引入axios

4、组件中引入使用

十一、路由

1、创建组件

javascript 复制代码
ng g component components/home

ng g component components/news

ng g component components/product

2、引入组件

3、配置路由

接下来就是输入路径就可以切换页面了

4、routerLink跳转页面 默认路由

选中当前页面高亮

十二、动态路由 & get 传值

1、get 传值

1.1、跳转、引入路由

1.2、接收

2、动态路由传值

2.1、跳转

2.2、接收

效果:

十三、动态路由的 js 跳转路由

1、路由引入十二点一样

2、get 传值

十四、父子路由(嵌套路由)

1、效果图

2、创建组件&路由

html 复制代码
ng g component components/home
ng g component components/product
...
ng g component components/home/welcome

3、根组件路由跳转

4、左边路由跳转

5、右边显示内容使用<router-outlet></router-outlet>占位

6、需要选中高亮每个父组件都要加上

html 复制代码
routerLinkActive="active"

十五、vdemo项目

地址:https://gitee.com/xu-feiyu/angular-basice

仓库地址:https://gitee.com/xu-feiyu/angular-basice.git

相关推荐
崔庆才丨静觅5 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅1 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅2 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊2 小时前
jwt介绍
前端
爱敲代码的小鱼2 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax