一:开发环境准备
下载安装angular
Node.js,webpack,脚手架搭建
查看node版本:node –v
Angular8只支持node10以上版本
查看npm版本:npm –v
删除已安装的旧版本的angular:cnpm uninstall –g @angular/cli
删除angular安装包
清除缓存:npm cache clean --force
全局安装angular最新版本:cnpm install –g @angular/cli@latest
查看是否安装成功:ng version
gnvm管理node
下载gnvm.exe放在安装node的路径下,双击gnvm.exe运行
以管理员身份运行:gnvm version
- 使用gnvm下载node:gnvm install 6.13
- 下载最新版本的node:gnvm update latest
- 查看安装了那些node版本:gnvm ls
- 使用某个版本:gnvm use 6.11.3
创建项目:ng new demo
报错:npm ERR code ERR_STREAM_WRITE_AFTER_END
解决方法:降低npm版本:npm i –g [email protected](会有不支持node10.16.3的警告)
再重新创建:ng new demo(cmd下)
切换到目录:cd demo
运行项目:ng serve –open(angular6需node10以上)
二:基础
组件/指令
模块/路由
依赖注入
rxjs/Http
组件及组件树:
1.创建组件
在component目录下创建header组件:ng g component comments/header
2.组件内容
组件内包含:html和css和ts
3.ts文件构成
class组件类和装饰器@Component构成
装饰器:赋予类更丰富的元数据,里面可以定义组件的模板template
@Component({
selector:’hello’, //匹配hello标签
template:’<p>{{greeting}}</p>’//这个模板会被插入到hello标签里
})
export class HelloComponent{
private greeting:string; //属性声明
constructor(){
this.greeting=’Hello Angular 2’} //属性赋值
}
4.属性和对象的声明和使用(ts里)
数据类型 | 声明 | 使用 |
属性 | public name:any=’张三’ | <div [title]=”name”> |
public name:string; | ||
constructor(){ this.name=’张三’ } |
||
对象 |
public userinfo:object={ name:’张三’, age:’20’ } |
{{userinfo.name}} |
5.数据的使用(html里)
插值:{{greeting}}
数据绑定:属性绑定,事件绑定,双向绑定
绑定的类型 | 包含内容 | 例子 |
Html绑定 |
public contant=’<div>123</div>’ <div [innerHTML]=’contant’> |
|
Class绑定 |
<div [ngClass]=”{ ‘box1’:ture }”> <li *ngFor=”let item of data1;let key=index” [ngClass]=”{red:key==0}”></li> |
|
Style绑定 |
<li [ngStyle]=”{‘color’:licolor}”></li> private licolor:ang=”red”; |
|
属性绑定 | value |
<input [value]=”myData”/> |
src |
pubilc picUrl:string=”../../../assets/a.JPG”; <img [src]=”picUrl”> |
|
事件绑定 |
键盘事件 keydown |
keyDown(e){ console.log(e); console.log(e.key); console.log(e.keyCode); } <input type=”text” (keydown)=”kayDown($event)”> |
键盘事件 keyup |
keyUp(e){console.log(e.target.value)} <input type=”text” (keyup)=”kayUp($event)”> |
|
鼠标点击事件 click |
//点击后获取数据 public title:any=”原始标题”; getData(){alert(this.title)} <button (click)=”getData”>点击</button> |
|
//点击后设置数据 public title:any=”原始标题”; setData(){this.title=”标题被改变”} <button (click)=”setData”>点击</button> |
||
//点击后获取对象 getDom(e){var dom=e.target;dom.style.color=”red”} <button (click)=”getDom($event)” >点击</button> |
||
双向绑定 | <input [(ngModel)]=”myData”/> |
双向绑定
1.导入模块
import {FormsModule} from ‘@angular/forms’
2.模块注册
@NgModule({
imports:[FormsModule]
})
3.使用:
public keywords:any;
<input type=”text” [(ngModle)]=”keywords”>
{{keywords}}
指令和命令
包括属性指令和结构指令,组件也是指令的一种
属性指令:改变组件外观或行为,如样式
结构指令:改变模板的Dom结构
指令 |
例子 |
解释 |
ng-app |
|
初始化应用程序 |
ng-init |
|
初始化数据 |
ng-module |
|
把元素绑定到应用程序 |
ng-repeat |
|
重复HTML元素 |
ng-module |
<form name=’myForm’> <input type=’email’ ng-module=’myText’ name=’myAddress’> <p>点击</p> {{myForm.myAddress.$valid}} {{ myForm.myAddress.$dirty}} </form> |
将输入域的值与变量绑定,可以为应用数据提供状态值 Invalid:输入值合法时为ture dirty:值改变时为 touched:通过触屏点击为ture error: |
*ngFor |
//数据
|
ngFor用作循环 |
ngSwitch | //定义数据 public score:ang=”1” //使用: <ul [ngSwitch]=”score”> <li *ngSwitchCase=”1”>已支付</li> <li *ngSwitchCase=”2”>未支付</li> <li *ngSwitchCase=”false”>支付失败</li> </ul> |
|
*ngIf | //定义数据: public flag:boolean=true; //使用 <div *ngIf=”flag”><div> |
用处 |
命令 |
解释 |
查看angular版本 |
ng version |
|
创建项目 |
ng new demo |
|
运行项目 |
ng serve –open |
|
创建有哪些参数 |
ng g |
|
创建组件 |
ng g component comments/header |
|
服务与依赖注入
依赖注入providers:组件引入外部构建(如服务)的一种机制
服务:实现单一目的的逻辑单元,如日志服务
服务→实例化→依赖注入→注入→组件
@component({
selector:’hello’,
template:’<p>greeting</p>’,
providers:[loggerService],
})
export class HelloCom1{
private greeting:string;
constructor(logger: loggerService){
this.greeting=’hello angular’;
logger.debug(‘构造函数执行完毕’)
}}
模块
包括文件模块和应用模块
文件模块:框架代码以模块形式组织,包括core核心模块(变换检测,依赖注入Component,Directive,ElementRef,Renderer等),comment通用模块(常用内置指令),forms表单模块(表单相关组件和指令),http网络模块(处理网络请求)及其他
应用模块:功能单元以模块形式主旨,即将组件,指令,服务进行包装
1.导入
import {Http} from ‘@angular/http’
2.模块定义
@NgModule({ //模块声明
declarations:[AppComponent,SomeDiretive], //包装指令或组件等
providers:[loggerService], //依赖注入
imports:[OtherModule], //导入其他模块
bootstrap:[ AppComponent], //设置根组件
exports:[SomeDirective], //导出组件或指令
})
export class AppModule {}
数据处理
pipe管道
类型 | 例子 |
日期转换 |
定义:public today:any=new Date() 使用:{{today | date : ‘yyyy-MM-dd HH-mm-ss‘}} |
大小写转换 |
转换成大写:{{data1 | uppercase}} 转换成小写:{{data1 | lowercase}} |
小数位数 |
格式:最少整数位数.最少小数位数-最多整数位数 {{data2 | number:1.2-4}} |
对象序列化 | {{ {name:’jennifer’}| json}} |
字符串截取 | {{ ‘jennifer’|slice:0:3}} |
管道链 | {{‘jennifer’ | slice:0:3 | uppercase}} |
表单
表单类型 | 关键词 | 例子 |
输入框 | text | <input type=’text’ /> |
单选 | radio |
<input type='radio' value="男" name="sex" id="sex1" [(ngModel)]="userInfo.userSex"><label for='sex1'>男</label> <input type='radio' value="女" name="sex" id="sex1" [(ngModel)]="userInfo.userSex"><label for='sex1'>女</label> ngModle 绑定Value值,当ngModel值和value值相同,默认被选中 |
多选 | checkbox |
<span *ngFor=’item of userInfo.hobby’> <input type=’checkbox’ [(ngModel)]=’item.checked’ /> </span> 双向绑定的是check的value,被选中则为true |
下拉列表 |
select option |
<select name=’’ [(ngModel)]=’item’> <option [value]=’item’ *ngFor=’item of userInfo.cityList’>{{item}}</option> </select> Select里双向绑定的是被选中的option的value |
P6(搜索记录和todolist)
输出 |
增 | 删 | |
搜索缓存 |
<input type=”text” [(ngModel)]=”keyword”/> <button (click)=”zengjia()”></button> <ul> <li *ngFor=”let item of arr; let key=index”>{{item}} <button (click)=”delete(key)”>删除</button></li> </ul> |
public arr:any[]=[]; public keyword:any; zengjia(){//检测是否存在相同值 if(this.arr.indexOf(this.keyword)==-1){ this.arr.push(this.keyword) } } |
delete(key){ this.arr.splice(key,1) } |
Todolist | |||
P7数据缓存
服务Stourage.service.ts | 根模块app.module.ts | 组件 | ||||||
1.1创建服务 ng g service services/storage |
2.1引入服务import {StorageService} from './services/storage.service'; |
3.1组件中引入服务 import {StorageService} from '../../services/storage.service'; |
||||||
1.2服务类中的内容
set(key:any,value:any){ localStorage.setItem(key,JSON.stringify(value)); } //从localstorage取出 get(key:any){ return JSON.parse(localStorage.getItem(key)) } //从localstorage移除 remove(key:any){ localStorage.removeItem(key) } |
2.2注册
@NgModule({ providers: [StorageService], }) |
3.2组件中注册constructor(public storage:StorageService) { } 3.3组件中使用服务类中的方法 this.storage.set('todolist',this.todoList); ngOnInit() { var localList=this.storage.get('todolist'); this.todoList=localList; } |
Dom操作
获取Document对象:
import { DOCUMENT } from '@angular/common';
constructor(@Inject(DOCUMENT) private doc: Document) { }
P8ViewChild用于Dom操作和组件方法调用
html:<div #wySlide></div> //1.Dom
ts:
class里{
private sliderDom: HTMLDivElement; //3.类型声明
@ViewChild('wySlider', { static: true }) private wySlider: ElementRef; //2.获取ElementRef
ngOnInit(){
this.sliderDom = this.wySlider.nativeElement; //4.获取Dom
}}
P9父子组件通信
通信方式 | 父组件中内容 |
子组件中内容 |
子获取父数据@Input |
public msgFromFather:any=”我是父组件传给子组件的值” <app-header [childMsg]=”msgFromFather”></app-header> |
import {Import} from ‘@angular/core’; @imprrt() childMsg:any; getMsg(){ console.log(this.childMsg) } |
子执行父方法@Input |
funFromFather(){alert(“父组件方法”)} <app-header [run]=”funFromFather”></app-header> |
import {Import} from ‘@angular/core’; @Input run:any getRun(){ this.run() } |
子获取整个父组件 |
public msg:any=”首页” <app-header [home]=”this”></app-header> |
import {Input} from ‘@angular/core’ @Input home:any; getFatherMag(){ alert(this.home.msg) } |
父获取子数据/方法@ViewChild |
<app-header #header></app-header> import {ViewChild} from ‘@angular/core’ @ViewChild(“header”) box2 getChildMsg(){ return this.box2.msg; } getChildFunc(){ return this.box.run() } |
public msg:any=”子组件的数据” run(){alert(“子组件的方法”)} |
子触发父方法并传值(父被动获取子数据) |
<app-header (outer)=”runParent($event)”></app-header> runParent(e){alert(outer)} |
<button (click)="setParent('传入值')"></button> import {Output,EventEmitter} from ‘@angular/core’ @Output() private outer=new EventEmitter<string>(); //实例化 setParent(data){this.outer.emit(data)} |
P10生命周期
异步,响应式
异步编程方法 | 服务内容(RequestService) | 组件里调用 | 解释 |
回调函数 |
getCallbackData(cb){ setTimeout(() => { var username = "jennifer"; cb(username); },1000); } |
construct(p){public request:RequestService} ngOnInit(){ this.request.getCallbackData( (data) => {console.log(data)} ) } |
cb函数作为getCallbackData的参数被传进,然后被异步函数setTimeOut调用 回调函数:将一个函数作为参数传入到另一函数 |
Promise |
getPromiseData(){ return new Promise((resolve,reject) => { setTimeout(() => { var username = "jennifer"; resolve(username); },1000); }) } |
construct(p){public request:RequestService} ngOnInit(){ this.request.getPromiseData().then( (data) => {console.log(data)} ) } |
getPromiseData里的异步函数setTimeOut执行成功后就调用resolve函数 Promise.then()设置resolve()和reject()内容 |
Rxjs |
import {Observable} from 'rxjs'; getRxjsData(){ let steam = new Obervable(observer =>{ setTimeout(() => { var username = "jennifer"; obsever.next(username); observer.error("失败") },1000); }) }
|
construct(p){public request:RequestService} ngOnInit(){ var rxjs = this.request.getRxjsData(); rxjs.subscribe( (data) => {console.log(data)} ) } |
subscript()设置 |
Rxjs取消订阅 |
import {Observable} from 'rxjs'; getRxjsData(){ let steam = new Obervable(observer =>{ setTimeout(() => { var username = "jennifer"; obsever.next(username); observer.error("失败") },3000); }) } |
construct(p){public request:RequestService} ngOnInit(){ var rxjs = this.request.getRxjsData(); var d = rxjs.subscribe( (data) => {console.log(data)} ) setTimeOut(() => {d.unsubscript()},1000) } |
|
Rxjs多次执行 |
import {Observable} from 'rxjs'; getRxjsData(){ let steam = new Obervable(observer =>{ setInterval(() => { var username = "jennifer"; obsever.next(username); observer.error("失败") },1000); }) } |
construct(p){public request:RequestService} ngOnInit(){ var rxjs = this.request.getRxjsData(); rxjs.subscribe( (data) => {console.log(data)} ) } |
P12请求数据
方式 | 根模块中app.module.ts | 组件中 | 组件中发出请求 |
get | import {HttpClientModule} from ‘@angular/common/http’; |
import {HttpClient} from ‘@angular/common/http’;(get请求) import
constructor(public http:HttpClient){} |
var api=http://xxx; this.http.get(api).subscribe(response => {console.log(response); }); |
post | import {HttpClientModule} from ‘@angular/common/http’; | constructor(public http:HttpClient){} |
const httpOptions = { headers:new HttpHeaders({‘Content-type’:’application/json’}) } var api=http://xxx/doLogin; this.http.post(api,{username:”张三”,age:”20”},httpOptions).subscribe( response => {console.log(response)}; ); |
jsonp | import {HttpClientModule, httpClientJsonpModule} from ‘@angular/common/http’; |
import {HttpClient} from ‘@angular/common/http’; constructor(public http:HttpClient){} |
var api=http://xxx/doLogin; this.http.jsonp(api,’callback’).subscribe(response =>{console.log(response)}) |
方法 | 内容 | 步骤 | ||
axios | 服务HttpService中使用axios |
1.1安装 cnpm install axios --save |
1.2新建服务 ng g service services/httpservice 服务中引入axios import axios from ‘axios’ |
1.3服务类中使用axios axiosGet(api){ return new Promise((resolve,reject) => { axios.get(api) .then(function(response){ resolve(response); }) }) } |
根模块app.moudule.ts |
2.1引入服务类 import {HttpService} from ‘./services/httpservice.service’; |
2.2注册 @NgModule({ providers:[ HttpService], }) |
||
组件中 |
3.1引入服务类 import {HttpService} from ‘../../services/httpservice.service’; |
3.2实例化 constructor(public httpService: HttpService,){} |
3.3发出请求 var api=http://xxx/doLogin; this. httpService. axiosGet(api).then((data) => { console.log(data) }) |
P13路由
配置理由
根路由模块中由引入组件 | 根路由模块中配置路由 | 使用路由 |
import {HomeComponent} from ‘./home/home.component’; import {newsComponent} from ‘./news/news.component’; import {newsContentComponent} from ‘./newsContent/newsContent.component’; |
const routes:Routes = [ {path:’home’,component:HomeComponent}, { path:’news’,component: newsComponent },//静态路由 { path:’newsContent/:aid’,component: newsContentComponent },//动态路由 {path:’**’,redirectTo:’home’} //默认路由
] |
<h1> <a [routerLink]=”[’/home’]”>首页</a> <a [routerLink]=”[’/news’]”>新闻</a> </h1> <router-outlet></router-outlet> |
路由传值(组件切换+传值)
app.routing.moudules.ts | 传出数据的组件 | 接受数据组件 | |
get传值 |
引入组件 import {HomeComponent} from ‘./home/home.component’; import {newsComponent} from ‘./news/news.component’; import {newsContentComponent} from ‘./newsContent/newsContent.component’; 路由配置(静态) const routes:Routes = [ {path:’home’,component:HomeComponent}, { path:’news’,component: newsComponent }, { path:’newsContent’,component: newsContentComponent }, {path:’**’,redirectTo:’home’} //默认路由 ] |
通过queryParams传值 <li *ngFor=”let item of list;let key =index”> <a [routerLink]=”[‘/newsContent’]” [queryParams]=”{aid:key}”>{{item}}</a> </li> |
引入ActivityRoute import {ActivatedRoute} from ‘@angular/router’; 声明 constructor(public route: ActivatedRoute){} 获取数据 ngOnInit(){ this.route.queryParams.subscribe((data) => { console.log(data) }) } |
动态路由传值 |
引入组件(同上) 路由配置(动态) const routes:Routes = [ {path:’home’,component:HomeComponent}, //普通路由 { path:’news’,component: newsComponent },//普通路由 { path:’newsContent/:aid’,component: newsContentComponent }, //动态路由 path:’**’,redirectTo:’home’} ] |
<li *ngFor=”let item of list;let key =index”> <a [routerLink]=”[‘/newsContent/’,key]”>{{item}}</a> </li> |
引入ActivityRoute import {ActivatedRoute} from ‘@angular/router’; 声明 constructor(public route:ActivitedRoute){} 获取数据 ngOnInit(){ this.route.params.subscribe((data) => {data}) } |
路由跳转(页面跳转+传值)
方法 | 跳转前页面 | 接收数据页面 |
路由get传值js跳转 |
触发跳转 <button (click)=” goNewsContent()”></button> |
接受数据组件newsContent引入ActivityRoute并声明 import {ActivatedRoute} from ‘@angular/router’; constructor(public route: ActivatedRoute){} ngOnInit(){ this.route.queryParams.subscribe((data) => { console.log(data) }) |
引入NavigationExtras import{Router, NavigationExtras} from ‘@angular/router’ construct中初始化 constructor(public router:Router){} 执行跳转,用NavigationExtras配置传参 goNewsContent(){ //定义数据 let msg: NavigationExtras = { queryParams:{‘userId’:’123’}, fragment:’anchor’ }; this.router.navigate([‘/news’], msg) } |
||
动态路由的js跳转 |
触发跳转 <button (click)=”goNewsContent()”>js路由跳转(动态路由)<button> <button (click)=”goHome ()”>js路由跳转(普通路由)<button> |
接收数据的组件 import {ActivatedRoute} from ‘@angular/router’; constructor(public route:ActivitedRoute){} ngOnInit(){ this.route.params.subscribe((data) => {data}) } |
引入 import {Router} from ‘@angular/router’; 初始化 constructor(public router:Router){} navigate跳转 goNewsContent(){ this.router.navigate([‘/newsContent/’ ,’1234’]) } goHome(){ this.router.navigate([‘/Home’]) } |
P15嵌套路由(父子路由)
场景:页面存在父子组件,点击时加载不同子组件
根路由模块配置路由app-routing.module.ts | 父组件home | |
创建home的子组件news ng g component component components/home/news 引入组件(缩进) import {HomeComponent} from ‘./home/home.component’; import {newsComponent} from ‘./news/news.component’; 配置嵌套路由 const routes:Routes = [ {path:’home’,component:HomeComponent children:[ { path:’news’,component: newsComponent }, {path:'**',redirectTo:'news'} //默认加载 ] ] |
<a [routerLink]=“['/home/welcome']">加载新闻组件</a> <a [routerLink]=”['/home/welcome']">加载通知组件</a> <div> <router-outlet></router-outlet> </div> |
|
- 创建home的子组件
ng g component component components/home/welcome