前端三大框架 :
Vue:开源项目,适合中小型项目
React:Facebook公司 ,适合中小型项目+RN手机端开发
Angular:Google公司,适合大型项目;简称NG,和Vue年相似
初识Angular______________________________
脚本方式: 适合最基本的入门, 实际开发没用.
脚手架方式: 属于工程化的开发方式, 利用脚手架生成完善的项目包.
安装脚手架: npm i -g @angular/cli --force 安装过程中, 有可能弹出选项, 询问是否要分享使用体验(y/N): 直接回车即可
![](https://i-blog.csdnimg.cn/blog_migrate/165f563ec4ad8721ef225631f8bbb3e5.png)
安装成功之后 可以通过ng v 查看Angular版本
![](https://i-blog.csdnimg.cn/blog_migrate/0210b7f0d21d287daabc8e32c470f2b9.png)
生成项目包, 关注 cmd 开启的位置, 在哪开 在哪生成
生成过程会有很多项目的询问, 都直接 回车 采用默认值即可; 不然容易会出现各种bug.
ng new 包名
例如: ng new ngpro
生成结果中, 只要有 这个 successfully 字样即可, 此行不是最后一行
![](https://i-blog.csdnimg.cn/blog_migrate/f276079e8928566c75d19365b5c92914.png)
启动项目: 在项目目录下 , 即 ngpro 目录下执行
ng serve --open
项目端口号: 4200
![](https://i-blog.csdnimg.cn/blog_migrate/43964d643be69272de1d8c09f9cfd0da.png)
项目的启动_______________________________________
当访问: localhost:4200 之后, 发生了什么?
访问当前计算机上, 端口号是4200的程序.
4200的程序, 就是 Angular 项目的自带服务器的端口号.
服务器的默认设定: index.html ; 来访用户如果不指定文件名, 则默认提供 index.html
根组件: <app-root></app-root>
angular采用 TypeScript 语言进行逻辑层编写
main.ts : 此文件是 webpack 打包工具, 在项目运行时会自动打包引入到 index.html 中
app/app.module.ts 此文件是项目的 根配置文件
app.component.ts 文件, 此文件就是项目的根组件, 类似于 React的 App.js 和 Vue的 App.vue
组件:
![](https://i-blog.csdnimg.cn/blog_migrate/3e774ba3a449927afa2490b6dc8bf49f.png)
组件的制作__________________________
Angular的组件 类似于 微信小程序 和 原生开发, 把一个页面拆分成3个文件: html , css , ts
angular的文件命名规范:
名字.作用.代码类型
例如: myc01.component.ts 名字是myc01, 作用是组件component, 代码类型ts文件
首先是在App文件目录下创建文件夹myc01
![](https://i-blog.csdnimg.cn/blog_migrate/3dbf52b43343865e9e07c26a07b02dcd.png)
然后创建在该文件夹下创建3个文件 分别为app.component.css,app.component.ts ,app.component.html
![](https://i-blog.csdnimg.cn/blog_migrate/4d0ee7c517fbaf201e88263aca6808e2.png)
html文件
<h1>Hello, 我的第一个组件</h1>
<!-- html文件就是 vue 的 template 区域 -->
css文件就是相应的一些样式这里就不写出来了
ts文件
// 在之前 安装插件的 前提下:
// ng-component
import { Component, OnInit } from '@angular/core';
/**
* 在原生开发中, html文件是主文件, 运行的是html文件, 在html中引入了 其它的css和js文件
*
* 在NG开发中, ts文件是主文件, 在ts文件中引入html 和 css
*/
@Component({
// 当前组件使用时的 标签名
selector: 'app-myc01', // <app-myc01></app-myc01>
// 引入关联的html
templateUrl: './myc01.component.html',
// 引入关联的css, 数组类型 说明可以引入多个css文件
styleUrls: ['./myc01.component.css'],
})
// 类名要求:大驼峰, 即首字母大写
export class Myc01Component implements OnInit {
constructor() {}
ngOnInit(): void {}
}
// 组件制作之后, 必须全局注册, 才能到 根组件中使用!
// app.module.ts
最后需要在app.module.ts文件中注册组件
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
// 引入组件, 然后注册
import { Myc01Component } from './myc01/myc01.component';
import { Myc02Component } from './myc02/myc02.component';
@NgModule({
// declarations: 用于注册组件
declarations: [
AppComponent, Myc01Component, Myc02Component
],
// imports: 引入模块
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
最后在根组件app.component.html中引用即可
<h1>HELlo word</h1>
<!-- 组件01 -->
<app-myc01></app-myc01>
<!-- 组件02 -->
<app-myc02></app-myc02>
快捷命令________________________
官方为了提高程序员的工作效率, 对很多操作提供了快捷的命令
项目启动命令:
ng serve --open : 启动服务 并 在默认浏览器自动打开
简化: ng s -o
生成组件命令
g generate component 组件名
generate: 生成
component: 组件
简化:
ng g c 组件名
例如: ng g c myc03
![](https://i-blog.csdnimg.cn/blog_migrate/771a357cb02c920fd109ebc7582a93ab.png)
这种快捷方式会给app文件夹生成对应文件 并且会在app.module.ts中自动引入该组件
插值 __________________________________
把 js 代码中的变量, 插入到 html 代码中: {{}}
在组件ts文件中定义一些数据
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc03',
templateUrl: './myc03.component.html',
styleUrls: ['./myc03.component.css'],
})
export class Myc03Component implements OnInit {
name = '天天';
age = 33;
married = true;
skills = ['vue', 'dom', 'axios', 'vue3.0'];
boss = { name: '天霸', age: 39 };
constructor() {}
ngOnInit(): void {}
}
// 面向对象
// class Demo {
// name = '东东';
// }
// 对象
// const obj = {
// name: '东东',
// };
组件的HTML文件中用插值语法
<p>myc03 works!</p>
<ul>
<li>{{ name }}</li>
<li>{{ age }}</li>
<li>{{ married }}</li>
<li>{{ skills }}</li>
<li>{{ boss }}</li>
<li>{{ skills[0] }}</li>
<li>{{ boss.age }}</li>
</ul>
<ul>
<!-- 支持各种运算符 -->
<li>{{ age + 4 }}</li>
<li>{{ age - 4 }}</li>
<li>{{ age * 4 }}</li>
<li>{{ age / 4 }}</li>
<li>{{ age % 4 }}</li>
</ul>
<ul>
<!-- 比较运算符 -->
<li>{{ age > 5 }}</li>
<li>{{ age >= 5 }}</li>
<li>{{ age < 5 }}</li>
<li>{{ age <= 5 }}</li>
<li>{{ age == 5 }}</li>
<li>{{ age != 5 }}</li>
</ul>
<ul>
<!--
逻辑运算符
&& 逻辑与 全真则真,有假为假
|| 逻辑或 全假为假,有真则真
! 逻辑非 非真为假,非假为真
-->
<li>{{ true && true }}</li>
<li>{{ true && false }}</li>
<li>{{ true || false }}</li>
<li>{{ false || false }}</li>
<li>{{ !true }}</li>
<li>{{ !false }}</li>
</ul>
<ul>
<!-- 三目运算符 -->
<li>{{ age > 18 ? "成年" : "未成年" }}</li>
<li>{{ married ? "已婚" : "未婚" }}</li>
</ul>
<ul>
<!-- 调用对象方法 -->
<li>{{ skills[0].toUpperCase() }}</li>
</ul>
属性绑定_________________________
快捷生成组件 ng g c myc04
在组件ts文件中定义一些数据
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc04',
templateUrl: './myc04.component.html',
styleUrls: ['./myc04.component.css'],
})
export class Myc04Component implements OnInit {
href1 = 'http://www.baidu.com';
href2 = 'http://www.bilibili.com';
constructor() {}
ngOnInit(): void {}
}
组件的HTML文件中用属性绑定语法
<p>myc04 works!</p>
<!--
在vue中:
:href="href1"
在NG中:
[属性名]="值"
-->
<a [href]="href1">百度</a>
<br />
<!-- 也支持插值方式 -->
<a href="{{ href2 }}">哔哩哔哩</a>
<!-- 如果是带有类型的值, 必须用 [] -->
<!-- 区分: false 和 'false' 绝对不一样, 'false'是字符串类型, 隐式转换为真 -->
<!-- 此写法是 html 代码写法, 在html中都是字符串类型 -->
<hr />
<button disabled="true">不可用按钮</button>
<button disabled="false">可用按钮</button>
<hr />
<!-- [属性名]="js代码" js代码中才有数据类型的概念 -->
<button [disabled]="true">不可用按钮</button>
<button [disabled]="false">可用按钮</button>
事件_________________________________
快捷生成组件 ng g c myc05
vue中: v-on:事件名="方法名" 或者 @事件名="方法名"
在组件ts文件中定义一些事件函数
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc05',
templateUrl: './myc05.component.html',
styleUrls: ['./myc05.component.css'],
})
export class Myc05Component implements OnInit {
num = 1;
doAdd() {
this.num++;
// react,小程序:setState 或 setData 主动触发刷新
// vue,angular: 自动检测数据变化, 更新DOM
}
constructor() {}
// 这里不是React, 没有this指向问题
show() {
alert('啊,疼!');
}
ngOnInit(): void {}
}
组件的HTML文件中用利用事件触发事件函数
<p>myc05 works!</p>
<!-- vue中: @click="show" -->
<!-- NG中: (事件名)="方法名()" 方法名必须带()结尾-->
<button (click)="show()">点我</button>
<hr />
<button (click)="doAdd()">{{ num }}</button>
双向数据绑定_____________________________
快捷生成组件 ng g c myc06
vue中: <input v-model='属性' />
在组件ts文件中定义一些数据
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc06',
templateUrl: './myc06.component.html',
styleUrls: ['./myc06.component.css'],
})
export class Myc06Component implements OnInit {
//定义个name 举例
name = 'comeintobud';
constructor() {}
ngOnInit(): void {}
}
在使用用双向绑定之前需要在app.module.ts中引入模块
![](https://i-blog.csdnimg.cn/blog_migrate/7fdbc079216e8d5c93ef110217a150c1.png)
// 引入 Forms 模块
import { FormsModule } from '@angular/forms';
@NgModule({
// declarations: 用于注册组件
declarations: [],
// imports: 引入模块
imports: [BrowserModule, FormsModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
组件的HTML文件中使用双向绑定对数据做更改
<p>myc06 works!</p>
<!--
双向数据绑定:
vue中: v-model
NG中: [(ngModel)]="值", 快捷提示: ng-model
-->
<!-- 关注: 默认双向绑定模块没有加载, 无法使用. -->
<!-- 需要: 到 app.module.ts 中进行加载 -->
<input type="text" [(ngModel)]="name" />
<p>{{ name }}</p>
特殊属性_______________________
快捷生成组件 ng g c myc07
网页内容: vue中: v-html
在组件ts文件中定义一些数据
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc07',
templateUrl: './myc07.component.html',
styleUrls: ['./myc07.component.css'],
})
export class Myc07Component implements OnInit {
//希望将h1编译成浏览器样式
data = '<h1>Hello World!</h1>';
constructor() {}
ngOnInit(): void {}
}
在组件的HTML文件中编译网页内容
<p>myc07 works!</p>
<div>
<!-- 插值写法: innerText -->
{{ data }}
</div>
<!--
vue中: v-html="data"
NG 中: [innerHTML]="data"
-->
<div [innerHTML]="data"></div>
动态样式_______________________
vue中:
:style="{样式名: 值}"
:class="{样式类名: true/false}" true生效 false无效
快捷生成组件 ng g c myc08
在组件ts文件中定义一些数据
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc08',
templateUrl: './myc08.component.html',
styleUrls: ['./myc08.component.css'],
})
export class Myc08Component implements OnInit {
//动态样式初始值
size = 17;
constructor() { }
ngOnInit(): void { }
}
组件的HTML中写动态样式
<p>myc08 works!</p>
<!-- 点击时, 执行 "" 中的代码 -->
<button (click)="size = size + 1">变大{{ size }}</button>
<!--
vue中:
:style="{fontSize: size+'px'}"
NG中:
[ngStyle]="{fontSize: size+'px'}"
-->
<div style="color: aqua" [ngStyle]="{ fontSize: size + 'px' }">Hello</div>
<!-- 通过条件, 显示不同的class -->
<!--
vue: :class="{样式类名: true/false}"
NG : [ngClass]="{样式类名:true/false}" true生效 false无效
-->
<div [ngClass]="{ success: size > 20 && size < 30, danger: size >= 30 }">
Hello Class
</div>
在css文件中定义样式便于动态绑定类
View Code
条件判断_________________
vue中: v-if v-else :本质上是 切换 DOM 的 添加和移除. 消耗更多的资源, 适合不频繁的切换
对应
v-show: 本质是切换 css 的 display 属性, 利用css实现元素的隐藏; 消耗资源少, 适合频繁切换.
快捷生成组件 ng g c myc09
HTML文件
<button (click)="score = score - 10" [disabled]="score == 0">减10分</button>
<button (click)="score = score + 10" [disabled]="score == 100">加10分</button>
<h4>分数:{{ score }}</h4>
<!--
vue: v-if
NG : *ngIf 快捷键 ng-if
-->
<div *ngIf="score < 60">很遗憾, 您的成绩不及格!</div>
<div *ngIf="score >= 60 && score < 80">及格了, 但是仍要继续努力.</div>
<div *ngIf="score >= 80">优秀 优秀!</div>
<!-- ng-if-else: 使用较少, 因为 if 可以解决大多数问题 -->
<ng-container *ngIf="score < 60; else xyz">
<h3>很遗憾, 您的成绩不及格!</h3>
</ng-container>
<!-- # 就是id, 用来做唯一标识 -->
<ng-template #xyz>
<h3>恭喜, 及格了!</h3>
</ng-template>
列表渲染______________________
vue中: v-for="(item,index) in arr" :key="index"
快捷生成组件 ng g c myc10
ts文件定义数据和函数
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-myc12',
templateUrl: './myc12.component.html',
styleUrls: ['./myc12.component.css']
})
export class Myc12Component implements OnInit {
data = ['vue', 'angular', 'react', 'ionic', 'jQuery', 'uniapp'];
teachers = [
// 数据项必须自带唯一标识id, 才能配合 trackBy 使用
{ id: 0, name: '亮亮' },
{ id: 1, name: '然然' },
{ id: 2, name: '东东' },
{ id: 3, name: '铭铭' },
{ id: 4, name: '小新' },
];
trackFunc = (index, item) => {
return item.id;
// return index; 也可以
};
// 自定义函数 把数字转数组
range(num: number) {
// TypeScript: 静态类型声明
// num: number 代表 参数num 是数字类型
const arr = [];
for (let i = 1; i <= num; i++) {
arr.push(i);
}
return arr;
}
constructor() { }
ngOnInit(): void {
}
}
HTML文件渲染
<ul>
<!--
vue中:
<li v-for="(item,index) in data" :key="index">{{item}}</li>
-->
<li *ngFor="let item of data">{{ item }}</li>
</ul>
<ul>
<li *ngFor="let item of data; let i = index">
<span>{{ i }}--</span>
<span>{{ item }}</span>
</li>
</ul>
<!-- angular: 不强制写 key 作为列表内容的唯一标识 -->
<!-- 只有出现删除这类操作时, 推荐使用 key 来提升效率 -->
<!-- angular中不是key 而是 trackBy -->
<ul>
<!-- trackBy: 值是一个函数, 此函数默认接受两个参数, 分别是 序号 和 item
此函数返回一个值, 作为唯一标识使用
-->
<li *ngFor="let item of teachers; trackBy: trackFunc">
{{ item.name }}
</li>
</ul>
<button *ngFor="let item of range(4)">{{ item }}</button>
综上写个例子
快捷生成组件 ng g c work
ts文件
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-work',
templateUrl: './work.component.html',
styleUrls: ['./work.component.css'],
})
export class WorkComponent implements OnInit {
todo = '';
todoList = ['吃饭', '睡觉', '打亮亮'];
doAdd() {
this.todoList.push(this.todo);
this.todo = '';
}
// TypeScript: 静态类型声明
doDel(index: number) {
// splice(a,b,c): 从序号a位置删除b个元素, 把c元素加入到a位置
this.todoList.splice(index, 1);
}
constructor() {}
ngOnInit(): void {}
}
HTML文件(注意双向绑定需要在app.module.ts中引入FromModule模块)
<div>
<div>
<!-- 双向绑定:必须手动到 app.module.ts 中注册 Forms 模块 -->
<input type="text" placeholder="请输入待办事项" [(ngModel)]="todo" />
<button [disabled]="todo.trim().length == 0" (click)="doAdd()">确定</button>
</div>
<div>
<ul>
<li *ngFor="let item of todoList; let i = index">
<span>{{ item }}</span>
<button (click)="doDel(i)" style="margin-left: 50px">删除</button>
</li>
</ul>
</div>
<div>
<h3 *ngIf="todoList.length == 0">暂无待办事项</h3>
<!-- if是通过操作 DOM 的删除来实现隐藏, 效率低 -->
<!-- 利用 css的 display:none; 实现隐藏效率高 -->
<!-- hidden: 隐藏 -->
<h3 [hidden]="todoList.length != 0">暂无待办事项</h3>
</div>
</div>