Angular_study
一、Angular创建项目
0、准备工作
使用npm命令安装angular/cli
npm uninstall -g @angular/cli //删除旧版本
cnpm install -g @angular/cli //安装
cnpm install -g @angular/cli@7.0.6 //指定安装版本
验证angular/cli
ng v
1、打开命令行进入你要创建项目的目录
2、创建项目
ng new 【项目名】
①直接安装
ng new demo1
②跳过npm i安装
ng new demo1 --skip-install
3、安装依赖
cnpm install
4、运行项目
ng serve --open
二、Angular介绍
1、目录结构分析
- e2e //端到端测试
- ng new demo1 //安装的第三方模块
- src //项目的所有文件都在里面
- app //组件,以及app.module.ts定义根模块
- assets //静态资源
- enviroments//包含为各个目标环境准备的文件
- favicon.ico
- index.html // 主页面
- main.ts //应用的主要入口
- polyfills.ts // 填充库能帮我们把这些不同点进行标准化
- style.css //全局样式
- test.ts //单元测试的主要入口点
- package.json //npm配置文件
2、创建使用组件
ng g component components/head
三、Angular组件以及组件中的模板合成完整
1、定义数据
声明属性的几种方式:
public 共有(默认) 可以在这个类里面使用,也可以在类外面使用 protect 保护类型 只有在当前类里和他的子类里可以使用 private 私有 只有在当前类里才能使用
//定义普通数据
public title = "我是新闻组件";
msg = "我是新闻组件";
username:string = "张三";
public student:any = 1223131; //(推荐)
public userInfo:object = {
username : "张三",
age : '20'
}
public content = "<h2>我是一个html标签</h2>";
//定义数组
public arr = ['1','2','3'];
public list:any[] = ['1',2,'3']; //推荐
public items:Array<number> = [1,2,3];
public userlist:any[] = [
{
name:'张三',
age:20
},
{
name:'李四',
age:21
},
{
name:'王五',
age:41
},
]
public cars:any[] = [
{
cate:'宝马',
list:[
{
title:'宝马x1',
price:'10w'
},
{
title:'宝马x2',
price:'20w'
},
{
title:'宝马x3',
price:'30w'
},
]
},
{
cate:'奥迪',
list:[
{
title:'奥迪Q1',
price:'10w'
},
{
title:'奥迪Q2',
price:'20w'
},
{
title:'奥迪Q3',
price:'30w'
},
]
},
]
2、绑定数据
①angular模板里绑定属性
//静态绑定
<div title = "我是一个div">
鼠标瞄上去看一下
</div>
//动态绑定
<div [title] = "student">
张三
</div>
②angular模板里绑定html
<span [innerHTML] = 'content'></span>
3、数据循环
①*ngFor 普通循环
<ul>
<li *ngFor = "let item of arr">
{{item}}
</li>
</ul>
<ul>
<li *ngFor = "let item of userlist">
{{item.username}} --- {{item.age}}
</li>
</ul>
<ul>
<li *ngFor = "let item of cars">
<h2>{{item.cate}}</h2>
<ol>
<li *ngFor = "let car of item.list">
{{car.title}} --- {{car.price}}
</li>
</ol>
</li>
</ul>
四、Angular中的服务以及数据持久化
1、创建服务命令
ng g service my-new-service
//创建到指定的目录下
ng g service services/storage
2、引入并配置服务
//①在app.module.ts中引入创建的服务
import { StorageService } from './service/storage.service';
providers: [StorageService], // 在NgMOdule里面的providers里面注入依赖服务
//②在目标模块中引入
import { StorageService } from '../../service/storage.service';
constructor(public storage:StorageService){
console.log(this.storage.get());
}
五、Angular中的Dom操作以及@ViewChild、Angular执行css3动画
//组件和指令初始化完成,并不是真正的dom加载完成
ngOnInit() {
}
//视图加载完成以后触发的方法 dom加载完成 (建议把dom操作写在这个里面)
ngAfterViewInit():void {
}
1、原生dom操作
2、ViewChild中的dom操作
<div #myattr> </div>
//在业务逻辑里面引入ViewChild
import {Component, ViewChild, ElementRef} from '@angular/core'
@ViewChild('myattr') myattra: ElementRef;
//获取并操作dom节点
ngAfterViewInit():void {
console.log(this.myattr.nativeElement);
this.myattr.nativeElement.style.width = '100px';
this.myattr.nativeElement.style.height = '200px';
}
3、侧边栏动画
<div>
内容区域
<button (click) = "showAside()"> 弹出侧边栏 </button>
<button (click) = "hideAside()"> 隐藏侧边栏 </button>
</div>
<aside id = "aside">这是一个侧边栏</aside>
#aside {
width: 200px;
height: 100%;
right: 0px;
top: 0px;
transfrom: translate(100%,0);
transition: all 2s;
}
showAside(){
var asideDom:any = document.getElementById('aside');
asideDom.style.transform = "translate(0,0)";
}
hideAside(){
var asideDom:any = document.getElementById('aside');
asideDom.style.transform = "translate(100%,0)";
}
六、Angular父子组件以及组件之间的通讯
父组件给子组件传值
- 子组件可以获取父组件的数据
- 子组件可以执行父组件的方法
子组件给父组件传值
- 父组件可以获取子组件的数据、
- 父组件可以获取子组件的方法
非父子组件
- 组件之间传值
- 共享方法
1、父组件给子组件传值-@input
父组件不仅可以给子组件传递简单的数据,还可以把自己的方法以及整个父组件传给子组件
①父组件调用子组件的时候传入数据/方法
<app-header [msg] = "msg"> </app-header> //传数据
<app-header [run] = "run"> </app-header> //传方法
<app-header [home] = "this"> </app-header> //传整个父组件
②子组件引入Inpu模块
import { Component, OnInit, Input } from '@angular/core';
③子组件中@Input接收父组件传过来的数据
export class HeaderComponent implements OnInit {
@Input() msg:string;
@Input() run:any;
@Input() home:any;
}
④使用数据/方法
alert(this.msg); //调用数据
this.run(); //调用方法
//调用组件
alert(this.home.msg); //调用数据
this.home.run(); //调用方法
2、父组件通过@ViewChild主动获取子组件的数据和方法
①、调用子组件给子组件定义一个名称
<app-footer #footerChild> </app-footer>
②、引入ViewChild
@ViewChild('footer') footer:any;
③、调用数据
alert(this.footer.msg);
3、子组件通过@Output触发父组件的办法
①、子组件引入Output和EventEmitter
import {Component, OnInit, Input,Output,EventEmitter} from '@angular/core';
②、子组件中实例化EventEmitter
@Output() private outer = new EventEmitter <string>();
//用EventEmitter和Output装饰器配合使用<string>指定类型变量
③、子组件通过EventEmitter对象outer实例广播数据
sendParent(){
this.outer.emit('msg from child')
}
④、父组件调用子组件的时候,定义接收事件,outer就是子组件中的EventEmitter对象outer
<app-header (outer) = "runParent($event)"></app-header>
⑤、父组件接收到数据会调用自己的runParent方法,这个时候就能拿到子组件的数据
runParent(e){
console.log(e); //子组件给父组件广播的数据
}
七、Angular中的生命周期函数
生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。
当Angular使用构造函数新建一个组件或者指令后,就会按照下面的顺序在特定的时刻调用这些生命周期钩子函数。
constructor() //【非生命周期函数】除了使用简单的值对局部变量进行初始化之外,什么都不应该做
ngOnChanges() //当被绑定的输入属性的值发生变化时调用(父子组件传递值的时候会触发)
ngOnInit() //请求数据一般放在这个里面
ngDoCheck() //检测,并在发生Angular无法或者不愿意自己检测的变化时作出反应(写一些自定义的操作)
ngAfterContentInit() //当把内容投影进组件之后调用
ngAfterContentChecked() //每次完成被投影组件内容的变更检测之后调用
ngAfterViewInit() //初始化完组件视图及其子视图之后调用(dom操作放在这个里面)
ngAfterViewChecked() //每次做完组件视图和子视图的变更检测之后调用
ngOnDestroy() //当Angular每次销毁指令/组件之前调用
八、Rxjs异步数据流编程
1、Rxjs处理异步
import { Observable } from 'rxjs';
let stream = new Observable((observer)=> {
setTimeout(()=> {
observer.next('timeout');
//observer.error();
},2000);
});
stream.subscribe(value => console.log(value));
Promise和Rxjs的用法基本相似。其实Rxjs相比Promise要强大的多。比如Rxjs可以中途撤回、可以发射多个值、提供了多种工具函数等。
2、Rxjs unsubscribe取消订阅
Promise创建之后,动作是无法撤回的。Observable不一样,动作可以通过unsubscribe()方法中途撤回,而且Observable在内部做了智能的处理。
//过一秒之后撤回刚才的操作
var undo = stream.subscribe(value => console.log(value));
setTimeout (()=>{
undo.unsubscribe(); //取消订阅
},1000)
3、Rxjs 订阅后多次执行
对于Promise来说,最终结果要么resolve,要么reject,而且都只能触发一次。如果在同一个Promise上多次调用resolve方法,则会抛异常;而Observable就不一样,它可以不断地触发下一个值,就像next()这方法的名字所暗示的那样。
let stream = new Observable((observer)=> {
let count = 0;
setInterval(()=> {
observer.next(count++);
},2000);
});
stream.subscribe(value => console.log(value));
4、Angular6.x以后Rxjs6.x的变化以及使用
RXJS6改变了包的结构,主要变化在import方式和operator上面以及使用pipe()
import { Observable } from 'rxjs';
import { map,filter } from 'rxjs/operators';
let stream = new Observable<any>((observer)=> {
let count = 0;
setInterval(()=> {
observer.next(count++);
},2000);
});
stream.pipe(
filter(val=>{
if(val%2 == 0){
return true;
}
})
)
.subscribe(value => console.log(value))
stream.pipe(
filter(val=>val%2==0),
map(value=>{
return value*value
})
)
.subscribe(value => console.log(value))
九、Angular中的数据交互
1、Angualr get请求数据
①、在app.module.ts中引入HttpClientModule并注入
import { HttpClientModule } from '@angular/common/http';
imports: [
BrowserMoudle,
HttpClientModule
]
②、在用到的地方引入HttpClient并在构造函数声明
import { HttpClient } from '@angular/common/http'; //当作一个服务
constructor(public http:HttpClient) {}
③、get请求数据
var api = "...";
this.http.get(api).subscribe(response => {
console.log(response);
});
2、Angular post提交数据
①、在app.module.ts中引入HttpClientModule并注入
②、在用到的地方引入HttpClient、HttpHeaders并在构造函数声明
import { HttpClient, HttpHeaders} from '@angular/common/http'; //当作一个服务
constructor(public http:HttpClient) {}
③、post提交数据
const httpOptions = {
headers: new HttpHeders({'Content-Type':'applications/json'})
};
var api = "127.0.0.1:800/userinfo";
this.http.post(api,{username:'张三',age:'20'},httpOptions).subscribe(response => {
console.log(response);
});
3、Angular Jsonp请求数据
4、Angular中使用第三方模块axios请求数据
①、安装axios
npm install axios --save
②、用到的地方引入axios
import axios from 'axios'
③、看文档使用
十、Angular中的路由
1、普通路由
1、创建一个带路由的项目
2、创建需要的组件
3、引入组件
4、配置路由
const routes: Routes = [
{ path: 'home', component: HomeCompoent},
{ path: 'newscontent/:id', component: NewsContentCompoent},
{
path: '',
redirectTo:'home',
pathMatch: 'full'
},
//匹配不到路由的时候加载的组件或者跳转的路由
{
path: '**',
redirectTo:'home',
}
];
5、找到app.component.html根组件模板,配置router-outlet显示动态加载的路由
<h1>
<a routerLink="/home">首页</a>
<a routerLink="/news">新闻</a>
</h1>
<router-outlet> </router-outlet>
2、动态路由的js跳转
①、引入
import { Router } from '@angular/router';
②、初始化
export class HomeComponent implements OnInit {
constructor(private router: Router){
}
}
③、使用
this.router.navigate(['/newscontent/','1243'])
3、路由get传值js跳转
①、引入NavigationExtras
import { Router , NavigationExtras } from '@angular/router';
②、定义一个goNewsContent方法执行跳转,用NavigationExtras配置传参
goNewContent(){
let navigationExtras: NavigationExtras = {
queryParams: {'session_id': '123'},
fragment: 'anchor'
};
this.router.navigate(['/news'],navigationExtras);
}