Angular 入门(一)
前端三大框架 :
Vue:开源项目,适合中小型项目
React:Facebook公司 ,适合中小型项目+RN手机端开发
Angular:Google公司,适合大型项目;简称NG,和Vue年相似
初识Angular______________________________
脚本方式: 适合最基本的入门, 实际开发没用.
脚手架方式: 属于工程化的开发方式, 利用脚手架生成完善的项目包.
安装脚手架: npm i -g @angular/cli --force 安装过程中, 有可能弹出选项, 询问是否要分享使用体验(y/N): 直接回车即可
安装成功之后 可以通过ng v 查看Angular版本
生成项目包, 关注 cmd 开启的位置, 在哪开 在哪生成
生成过程会有很多项目的询问, 都直接 回车 采用默认值即可; 不然容易会出现各种bug.
ng new 包名
例如: ng new ngpro
生成结果中, 只要有 这个 successfully 字样即可, 此行不是最后一行
启动项目: 在项目目录下 , 即 ngpro 目录下执行
ng serve --open
项目端口号: 4200
项目的启动_______________________________________
当访问: 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
组件:
组件的制作__________________________
Angular的组件 类似于 微信小程序 和 原生开发, 把一个页面拆分成3个文件: html , css , ts
angular的文件命名规范:
名字.作用.代码类型
例如: myc01.component.ts 名字是myc01, 作用是组件component, 代码类型ts文件
首先是在App文件目录下创建文件夹myc01
然后创建在该文件夹下创建3个文件 分别为app.component.css,app.component.ts ,app.component.html
html文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<h1>Hello, 我的第一个组件</h1> <!-- html文件就是 vue 的 template 区域 -->
css文件就是相应的一些样式这里就不写出来了
ts文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 在之前 安装插件的 前提下: // 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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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中引用即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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
这种快捷方式会给app文件夹生成对应文件 并且会在app.module.ts中自动引入该组件
插值 __________________________________
把 js 代码中的变量, 插入到 html 代码中: {{}}
在组件ts文件中定义一些数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件中用插值语法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件中定义一些数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件中用属性绑定语法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件中定义一些事件函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件中用利用事件触发事件函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件中定义一些数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 引入 Forms 模块 import { FormsModule } from '@angular/forms'; @NgModule({ // declarations: 用于注册组件 declarations: [], // imports: 引入模块 imports: [BrowserModule, FormsModule], providers: [], bootstrap: [AppComponent], }) export class AppModule {}
组件的HTML文件中使用双向绑定对数据做更改
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件中定义一些数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件中编译网页内容
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件中定义一些数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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中写动态样式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件定义数据和函数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件渲染
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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模块)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<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>