angular指令整理
1.*ngFor:除可以循环数组之外,内置的几个变量可以通过起别名的方法给导出来使用,不能直接在列表中使用,而是要通过起别名的方法(first as isFirst)
- index
- first
- last
- count
- even
- odd
<tr *ngFor="let item of list; index as i; first as isFirst">
<td *ngIf="isFirst">...</td>
</tr>
父组件的值传到子组件
//父组件挂载变量
<child-component [msg]=msg></child-component>
//子组件引入input,然后用@input声明传递过来的变量
import {input} from '@angular/core'
@input() msg;//msg就引入了
子组件传值给父组件
利用的是事件的广播
//父组件挂载函数,函数存在参数$event
<child-component [msg]=msg (parentFun)='myFunc($enent)'>
</child-component>
//子组件引入@output EventEmitter并声明并调用emit广播
import {input,output,eventEmitter} from '@angular/core'
@output() parentFun = new EventEmitter();//声明
this.parentFun.emit(this.data);
父组件通过@viewchild获取子组件数据和方法
//给子组件#命名
<child-component #child></child-componet>
//父组件引入viewChild并@viewChild声明并命名子组件
import {viewChild} from '@angular/core';
@viewChild("child",{static:true}) myChild;//子组件命名为myChild
//通过this.myChild.xxx获取数据、修改数据、执行函数
//父组件也可以通过getElementById("xxx")取得父组件实例进行和上步一样的操作
服务service
1、创建服务到指定的目录下ng g service service/storage,默认的服务页面会有:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
constructor() { }
// 在这里写服务的具体内容
}
2、在app.module.ts中引入并注册服务
import { StorageService } from './service/storage.service';
//在provider内部注册服务
@ngModule({
providers: [StorageService]
})
3、使用的页面引入服务并注册到构造函数中
import { StorageService } from '.../../service/storage.service'
//构造函数声明
constructor(private storage:StorageService)
angular带参跳转
- 页面html中使用routerLink属性跳转到目标路径,并使用queryParams绑定数据
// 方法1:查询参数形式
<a [routerLink] = "/product" [queryParams]="{id:1}">跳转</a>
// 此时浏览器地址类似于: http://localhost:3000/product?id=1
// 获取参数使用ActivateRoute,其中的snapshot
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.productId = this.route.snapshot.queryParams['id'];
}
// 方法2: 在路径中传递参数
// 路由配置path加上:id
// 修改路由连接的参数
<a [routerLink]="['product',1]"></a>
// 使用this.route.snapshot.params获取参数
this.route.snapshot.params['id'];
- navigate
// 首先这两个的差别还不是很明显
// 基本语法,需要引入router
import { Router } from "@angular/router";
constructor(private router: Router){}
// 不带参数,参数为字符串,即路径
this.router.naviage('question-board/questions-detail')
// 带参传递,参数为数组,
this.router.navigate(['user',params]);
// 使用时的各种设置
// 默认情况下,是根据根路由进行跳转,即如果不设置的情况下,要把路径写完整
// 相对于当前路由跳转,需要使用ActivatedRoute,也是从@angular/router里面引入
import { Router, ActivatedRoute } from '@angular/router';
constructor(private router:Router, private route:ActivatedRoute){}
this.router.navigate(['user',params],{relativeTo: route});
// 路由中传递查询参数
this.router.navigate(['user',params],{queryParams:{id:1}});
// 保留之前路由中的查询参数,默认是false
this.router.navigate(['view', 1], { preserveQueryParams: true });
// 路由中锚点跳转/user/1#top
this.router.navigate(['user', 1],{ fragment: 'top' });
angular深入子组件内部修改样式
如果想要深入到子组件内部修改样式:
:host ::ng-deep .innerClass span {
display: inline-block;
}
:host 伪类选择器,指定当前component
::ng-deep,和/deep/,>>> 一样为深度选择器,但是即将启用(/deep/,>>>,::ng-deep都将弃用,新标准没有出来前,统一使用::ng-deep,为以后的新标准做准备)。
angular监听事件:
- 使用HostListener,能监听全局,window层的事件
// 引入HostListener
import { OnInit, HostListener } from '@angular/core'
//使用,监听全局scroll或者全局key down
@HostListener('window:scroll', ['$event']) public scrolled = ($event) => {
console.log($event);
}
@HostListener('window:keydown', ['$event']) public onKeydown = ($event) => {
console.log($event);
}
@HostListener()和@HostBinding()
HostBinding相当于绑定全局类/样式/属性等
// 实现一个监听输入随机变色的demo
possibleColors = [
'darksalmon', 'hotpink', 'lightskyblue', 'goldenrod', 'peachpuff',
'mediumspringgreen', 'cornflowerblue', 'blanchedalmond', 'lightslategrey'
];
@HostBinding('style.color') color: string;
@HostBinding('style.borderColor') borderColor: string;
@HostListener('keydown') onKeydown() {
const colorPick = Math.floor(Math.random()*this.possibleColors.length);
this.color = this.borderColor = this.possibleColors[colorPick];
}
- 使用原生的事件监听
在HostListener中只能监听当前宿主元素的事件,当需要监听普通元素的事件时,使用原生的addEventListener方法:
private removeListenerFromRmsContent() {
let content = document.querySelector('.content');
(content as HTMLElement).removeEventListener('scroll', this.listenScrollEvent);
}
private addListenerToRmsContent() {
// add event listener to rms-content
let content = document.querySelector('.content');
(content as HTMLElement).addEventListener('scroll', this.listenScrollEvent);
}
有add就要有remove
位置:
- .add在ngAfterViewInit
- remove在ngOnDestroy
angular生命周期
依然是三个重要的生命周期:
- ngOnInit:在这里能拿到所有的方法和属性,也可以拿到dom,但是只能获取却不能操作
- ngAfterViewInit:这里能够操作dom,关于dom相关的操作应该放在这里,动态渲染的dom应该先this.changeDetectorRef.detectChanges();再进行操作。
- ngOnDestory:主动销毁监听函数等方法写在这里。
angular 数组(引用数据类型)改变进行页面更新:
情景:一个组件的渲染依赖于某个数组,数组会在操作过程中进行push和splice操作,但是改变的数据并不会被检测到并更新。
方法:在更新的数据后面加一句:
this.vals = this.vals.slice();
angular的一些功能
- 动态设置块级元素的宽高(单位px)
属性[style.width.px]或者属性[style.height.px]
value是有返回值的函数或者是一个ts值。
<div [style.width.px]="getContentWidth()" [style.height.px]="aLength"></div>
angular管道
1.内置管道: 很多
2.自定义管道:
举个例子:
需要页面显示用户头像:如果有头像就显示头像,如果没有头像,就按照性别显示男女生头像,如果头像和性别都没有,就显示default头像:
- 编写管道文件xxx.pipe.ts
需要引用的是@angular/core 的pipe和pipeTransform
使用@pipe({ name: ‘xxxx’ })来装饰类
transform接受0或者多个参数,它决定了返回值
import { Pipe, PipeTransform } from 'angular/core'
const sexList = ['', '男', '女'];
const headImg = ['./assets/images/default.png', './assets/images/boy.png', './assets/images/girl.png']
@pipe({name:'portrait'})
export class Portrait implements PipeTransform {
transform(value): string{
let url = '';
if (value === '男' || value === '女') {
let idx = sexList.indexOf(value);
url = headImg[idx];
} else {
url = value ? value : headImg[0];
}
return url;
}
}
- 在shareModule中导出:
import { NgModule } from '@angular/core';
import { Portrait } from './pipe/comm.pipe';
@NgModule({
declarations: [
...
Portrait
],
exports: [
...
Portrait
]
})
export class SharedModule {
}
- 使用的地方导入这个commonModule
- 页面的基本使用:
<img src="{{studentInfo['headUrl'] || studentInfo['sex']} | portrail}"/>
- ts文件中使用管道:
constructor(
private portrail: Portrail
)
this.portrail.transform(xxx);