1.安装node.js
2.安装angular
npm i -g @angular/cli
3.创建项目
ng new 项目名
4.文件结构:
e2e:测试目录
src:
{
index.html:网站主页面
main.ts:应用主入口
}
src-app: //模块和组件
{
app.component.css //模块/组件的css样式
app.component.html //模块/组件的html页面
app.component.ts //模块/组件的程序文件
}
src-assets: 存放静态资源文件
src-environments :环境配置
src-favicon.ico 图标
src-index.html 整个应用的根html
main.ts 整个web应用的入口点,脚本执行的入口点
polyfills.ts导入一些必要的库
styless.css全局样式文件
angular-cli.json 命令行工具的配置文件,
karma ,protractor.conf.js 单元测试的追踪器
package.json npm配置文件,列明了当前应用所使用的依赖包
tslint.json tslint的配置文件
5.运行
ng serve --open 或者npm start
项目根模块:app.module.ts
定义的组件都需要在app.module.ts文件里先进行import引入
然后在@NgModule({deckartions:[]})声明
定义组件模板的两个方式:
1.使用templateurl引用一个html文件
2.使用template +es6的模板字符串
定义组件样式的两个方式:
1.使用styleUrls引用一个css文件
2.使用style +es6的模板字符串
元数据:通过装饰器描述组件
使用命令创建模块
ng g module customers --routing=true
生成的模块文件有个路由文件(customers-routing.modules.ts)和ts(customers.modules.ts)文件
在项目的根路由文件引入模块
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'CustomersModule' }, //重定向
{ path: 'CustomersModule',loadChildren:()=>import('./customers/customers.module').then(m=>m.CustomersModule)}
];
使用命令创建组件
先打开需要创建组件的模块,然后进入到模块命令行中,使用命令
ng generate component 组件名 ##只能小写,不能大写
或者缩写
ng g c 组件名 ##只能小写,不能大写
例如 ng g c hello
就会生成一个hello的文件夹,里面有几个文件
我们可以在hello.component.html写一段文字
我是第一个组件
在模块的路由文件里引入组件
import { CustomersChildComponent } from './customers-child/customers-child.component';
import { CustomersHelloComponent } from './customers-hello/customers-hello.component';
const routes: Routes = [
{path:"",component:CustomersChildComponent},
{path:"hello",component:CustomersHelloComponent}
];
然后保存,等编辑器重新编译之后,输入刚才模块的路由,就可以显示出来了
http://localhost:4200/CustomersModule //url地址/模块名称
http://localhost:4200/CustomersModule/hello //url地址/模块名称/模块里的组件
需要在根模块引入FormsModule,
然后在import里添加FormsModule,[(ngModel)]=“text”,
父组件到子组件@input(), @input(num) mynum 改名,当名字num重复的时候,可以使用此方法改名
子组件到父组件@Output() change = new EventEmitter(),
@Output(change) changea =new EventEmitter();
改名
属性绑定:class
事件绑定:(click)=“clicked()”,(click)=“click1($event)”
自定义事件:
父组件:<子组件>
子组件:先引入EventEmitter,Output,
然后再获取自定义事件:@Output() myClick=new EventEmitter()
触发自定义事件:
*ngfor:循环
*ngif:判断
*ngSwitch: ngSwitch,ngSwitchCase,ngSwitchDefault
```html
style.属性 style.color="'red'",style.color="true?'red':'blue'",style.font-size.px="10"
*ngStyle:[ngStyle]="{‘color’:‘red’,‘font-size’:‘80px’}"
*ngClass:[ngClass]="{‘box’:true,‘container’:false}"
ngNonBindable:类似于转义字符,使用了之后表示范围内的{{}}不进行编译,显示字符串
属性指定:
[(ngModel)]:双向绑定
服务
.server.ts结束的文件
组件开发步骤:
3.引入组件,并声明
4.在要使用组件的位置,通过seletor的名称来使用,
表单:
```javascript
重置为空 this.userForm.reset()
重置为默认数据 this.userForm.reset({
//默认数据
name:"aa",
pwd:"123456"
})
//或者先将对象定义在外面,然后在this.userForm.reset(对象名)
user={
name:"aa",
pwd:"123456"
}
this.userForm.reset(this.user)
设置值 setValue
this.userForm.setValue({
name:"aa",
pwd:"123456"
})
//将表单里的值设置为设置的值,需要设置全部的值,只设置其中部分值,会报错
设置部分值 patchValue
this.userForm.setValue({
pwd:"123456"
})
//当需要只设置部分值的时候,可以用这个
1.父组件-子组件
父组件
export class 父组件名称 implements OnInit{
name="aa"
age="11"
}
…
子组件接收,@Input() 只能取值,不能监听值的变化
export class 子组件名称 implements OnInit{
@Input() name; // @Input('父组件里的参数名') 子组件使用的参数名 @Input("name") myName
@Input() age;
}
如果需要监听值的变化,需要使用set和get
@Input()
set age(age:number){
//设置age
}
get age(){
//获取age
}
2.子组件到父组件
父组件
<child [name]="name" [age]="age" (myAgeChange)="ageChange()"></child>
ageChange(){
this.age=99
}
子组件
<button (click)="changeFaAge()"></button>
@Output() myAgeChange = new EventEmitter()
changFaAge(){
this.myAgeChange.emit()
}
3.父组件可以通过子组件的模板变量获取到子组件里的事件
父组件
父组件在挂在子组件的时候,给子组件加上模板变量 #child,
然后在父组件中就可以通过子组件的模板变量名称直接获取子组件里的事件
child.changeFaAge
<button (click)="child.changeFaAge"></button>
<child #child [name]="name" [age]="age" (myAgeChange)="ageChange()"></child>
子组件
<button (click)="changeFaAge()"></button>
@Output() myAgeChange = new EventEmitter()
changFaAge(){
this.myAgeChange.emit()
}
4.父组件调用@viewChild获取子组件的事件
@viewChild(子组件名称)
private child:子组件名称 //child定义的变量名称
controlChild(){
this.child.changFaAge()
}
组件样式
在组件的元数据定义styles,styles可以接受一个包含css样式代码的字符串数组
@Component({
selector:“app-style”
template:
,hello world
styleUrls:[‘css文件路径’]
styles:[h3{font-size:20px;}
,*{color:red;}
]
//当styleUrls和styles同时存在的时候,可能只有下面的那个生效,
//一般建议把样式写在css文件中,然后再通过styleUrls引入
})
视图的封装模式
组件的css样式被封装进了自己的视图中,从而不会影响到应用程序的其他部分,
通过在组件的元数据上设置视图封装模式,我们可以分别控制每个组件的封装模式
可选的封装模式分为三种:原生(Native),仿真(Emulated),无(None).
原生(Native)
通过使用浏览器原生的shadow dom来为组件的宿主元素添加一个shadow dom,组件的样式
包裹在shadow dom中,不进不出,外面的样式进不来,组件样式出不去
仿真(Emulated)
通过预处理css代码来模拟shadow dom的行为,把css样式局限在组件视图中,外面的全局样式可以进来,
组件的样式出不去
无(None)
把css样式添加到全局中,从本质来说,跟组件的样式直接放在html文件一样,能进能出
使用
先引入ViewEncapsulation
通过组件元数据中的encapsulation来设置
encapsulation:ViewEncapsulation.Native
:host伪类选择器
修改宿主的样式,宿主:即子组件依赖的父组件
子组件css文件
:host{
color:red;
}
使用这个,即这个子组件的父组件就会增加样式
:host(.active){
border:3px solid #fff
}
只有当宿主同时带有active css类的时候才会生效
:host-context
类似:host()形式使用在当前组件宿主元素的祖先节点查找css类
直到找到文档的根节点为止,在与其他选择器组合使用时会非常有效
:host-context(.italic) h3{
color:red;
}
在当前组件宿主元素的祖先节点查找italic类,如果找到这个类名了,他里面的h3就会改变颜色
1.要使用哪个钩子函数,就先引入
import {OnInit} from ...
再实现
export class 组件名 implements Onint...
再使用
ngOnInit(){
....
}
当angular(重新)设置数据绑定输入属性时相应。该方法接受当前和上一属性值的simpleChanges对象,当被绑定的输入属性的值发生变化时调用,首次调用一定会发生在ngOnInit()之前。
在angular第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。
在第一轮ngOnchanges()完成之后调用,只调用一次
检测,并在发生angular无法或不愿意自己检测的变化时作出反应,在每个angular变更检测周期中调用,在ngOnChanges()和ngOnInit()之后
当把内容投影进组件之后调用,第一次ngDoCheck()之后调用,只调用一次,只适用于组件
每次完成被投影组件内容的变更检测之后调用,ngAfterContentInit()和每次ngDoCheck()之后调用,只适用于组件
初始化完组件视图及其子视图之后调用。第一次ngAfterContentChecked()之后调用,只调用一次,只适合组件。
每次做完组件视图和子视图的变更检测之后调用。ngAfterViewInit()和每次ngAfterContentChecked()之后调用,只适合组件
当angular每次销毁指令/组件之前调用并清扫,在这里反订阅可观察和分离事件处理器,以防内存泄漏
在绑定之前,表达式的结果可能需要一些转换。例如,可能希望把数字显示成金额、强制文本变成大写,或者过滤列表以及进行排序。
Angular管道对象这样的小型转换来说是个很方便的选择。
管道是一个简单的函数,它接受一个输入值,并返回转换结果。
DatePipe:事件管道,根据区域设置规则格式化日期值
{{ value | currency [ : currencyCode [ : display [ : digitsInfo [ : locale ] ] ] ] }}
UpperCasePipe:大写管道,将文本转为全部大写
LowerCasePipe:小写管道,将文本全部转为小写
SlicePipe:首字母转换为大写
CurrencyPipi:货币管道,将数字转换成货币字符串
DeprecatedPercentPipe:百分比管道,将数字格式化为百分比
TitleCasePipe :将文本转为标题大小写,单词首字母大写,其余部分小写
JsonPipe:json管道,将值转换为json格式
DecimalPipe:字符串管道,将数字转换为字符串
它们用于模块表达式中,只要使用管道操作符| 就可以了
管道操作符会把它左侧的表达式结果传给它右侧的管道函数,还可以通过多个管道串联表达式。
<div class="alert alert-warning">
<p>{{title|uppercase }}p>
<p>{{title|uppercase|lowercase }}p> //链式管道
<p>{{this|json}}p>
<p>{{time|date:'yyyy-MM-dd'}}p>
<p>{{number|percent}}p>
<p>{{number|currency:'CNY'}}p>
<p>{{birthday| date:format }}p>
div>
export class AppComponent {
title = 'app';
name = '张三丰';
time = new Date();
number = 1.123;
birthday = new Date(2017,11,11)
flag = true;
format(){
return this.flag?'yyy-MM-dd':'MM-dd'
}
show(str: string) {
str += '---测试';
return str;
}
}
import { Pipe, PipeTransform } form '@angular/core'; //引入PipeTransform是为了继承transform方法
@Pipe({ name: 'sexReform' }) //name属性值惯用小驼峰是写法, name的值为html中| 后面的名称
export class SexReformPipe implements PipeTransform {
transform(value: string, args?: any): string {
switch(value){
case 'male': return '男';
case 'female': return '女';
default: return '雌雄同体';
}
}
}
//在组件中使用自定义管道
// demo.component.ts
export Class DemoComponent {
sexValue = 'male';
}
// demo.component.html
<span>{{ sexValue | sexReform }}</span>
依赖注入:是一种编程模式,可以让类从外部源中获得它的依赖,而不必亲自创建它们。可以在两个地方注入依赖:
创建服务快捷指令
ng-server
NgModule:全局注册;
在根目录的module.ts文件里引入,然后在providers:[]里进行全局注册
在组件中使用:
1.在组件的component.ts文件里引入
2.在OnInit里通过构造器进行依赖注入
constructor(private 自定义变量:上方引入的服务名)
3.在数据初始化ngOnInit里使用
this.自定义变量.服务里的方法
例:
//新建的服务文件为user.service.ts
import {Injectable} from '@angular/core';
@Injectable()
export class UserListService{
users:[]=[
{name:"zhangsan",age:10},
{name:"zhangsana",age:11},
{name:"zhangsanb",age:12},
{name:"zhangsanc",age:13},
];
getUser(){
return this.users
}
}
//在根目录app.module.ts文件里引入服务
import {userservice} from './user.service.ts'
//在项目根目录进行全局注册
providers:[userservice]
//在组件中使用服务
//引入服务
import {userservice} from './user.service.ts'
//在OnInit里通过构造器进行依赖注入
constructor(private userservice:userservice)
//使用服务
users=[]
ngOnInit(){
users = this.userservice.getUser()
}
Component:局部注册
//不需要在根目录引入和注册服务,直接在所需要使用的组件里注入
//组件 user-list-components.ts
//引入服务
import {userservice} from './user.service.ts'
@Compinent({
selector:"user-list-components",
providers:[userservice]
})
//在OnInit里通过构造器进行依赖注入
constructor(private userservice:userservice)
//使用服务
users=[]
ngOnInit(){
users = this.userservice.getUser()
}
//1.根目录的module.ts里引入httpclient
import {HttpClientModule} from '@angular/common/http';
imports: [
BrowserModule,
AppRoutingModule,
HttpClientModule //加载httpclient
],
2.在组件的component.ts文件里导入httpclient,如果有post请求,还需要导入HttpHeaders
import { HttpClient, HttpHeaders } from "@angular/common/http";
3.在组件的构造器里定义一个http
constructor(
private http: HttpClient,
) { }
4.设置headers
headers = {
Headers: new HttpHeaders({
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
}),
};
5.使用http请求
this.http
.get<any>("接口地址", {
headers: {},
params: {},
})
.subscribe((res) => {
//请求成功的回调
}
}),
(err: any) => {
//请求失败的回调
console.log(err);
};
1.在项目的根目录里新增一个proxy.conf.json文件
2.在proxy.conf.json里设置代理
{
"/api": {
"target": "请求的接口地址",
"secure": false,
"changeOrigin": true
}
}
3.在package.json里配置启动代理
"start": "ng serve --proxy-config proxy.conf.json",
4.重新运行项目,就可以正常请求到接口了
npm start
{path:"home",compont:home}
<a routerLink='home'></a> //等同于vue的 router-link to=''
<router-outlet></router-outlet> //路由出口
//重定向路由
{path:"",redirectTo:"home",pathMath:"full"}
//参数路由
{path:"home/:id",compont:home}
使用
<a routerLink='home/12'></a>
//在组件里获取参数,router-params.component.ts
//先引入Docheck钩子函数和路由核心库
import {DoCheck} from '@angular/core'
import {Router,ParamMap} from '@angular/router'
//获取参数snapshot.paramMap.get('路由里定义的变量名')
export class RouterParamsComponent implements OnInit,DoCheck{
id;
constructor(private route:ActivatedRoute,private router:Router){}
ngDoCheck():void{
this.id = this.route.snapshot.paramMap.get('id')
}
}
配置子路由
{path:"home",compont:home,
children:[
{path:"homea",compont:homea}, //子路由地址:/home/homea
{path:"homeb/:id",compont:homeb}, ///home/homeb/1
]}
注意:子路由需要在他的父路由的html中添加路由出口,否则会跳转无响应
//通过事件跳转路由
this.router.navigateByUrl('路由地址')
//还可以设置属性{skipLocationChange:true},实现页面跳转但路由不发生变化
this.router.navigateByUrl('home',{skipLocationChange:true})
//还可以使用navigate进行路由跳转
this.router.navigate(['home'])
//传参
this.router.navigateByUrl('home/1')
this.router.navigate(['home','1'])