传值方式
常用传值方式有:
存储:先存后取,不能同步更新
即时传递:值变动时,同步更新
一次性传递:仅使用一次,不再更新
存储
存储方式有多种,常用的:
本地存储:localStorage、sessionStorage
localStorage.getItem(key);
localStorage.setItem(key,value);
sessionStorage.getItem(key);
sessionStorage.setItem(key,value);
服务存储
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
private data: string;
getData(): string {
return this.data;
}
setData(value: string): void {
this.data = value;
}
}
一次性传递
仅使用一次即可,多用于浏览器url拼接参数。
http://xxx?data=1
即时传递
值变动时,同步更新,传值要避免传Object类型的值,防止值被共用导致问题。(Object传递的是引用路径)
1.组件关系--父向子传值
通过@input实现父向子的传值
父组件
<div class="app-item">
<app-item-detail [item]="currentItem"></app-item-detail>
</div>
子组件
ngOnChanges(changes: SimpleChanges) {
for (const propName in changes) {
const chng = changes[propName];
// 获取值后调用对应方法
}
}
也可以通过在父组件中获取子组件模块去达到传值效果
父组件html
<div class="app-item">
<app-item-detail #appItemDetail></app-item-detail>
</div>
父组件ts
// 在父元素中获取子元素组件
@ViewChild('appItemDetail') appItemDetail: AppItemDetailConponent;
// 可以直接调用子元素的方法
this.appItemDetail.forchange(data)
2.组件关系--子向父传值
子向父元素传值大多用的都是@output方法
父组件html
<div class="app-item">
<app-item-detail (itemEvent)="addItem($event)"></app-item-detail>
</div>
子组件ts
// 在子元素组件定义标签上名称一样的event
@Output() itemEvent = new EventEmitter();
// 通过emit可以将值传递给父元素
this.itemEvent.emit(value);
3.组件关系--共同父元素
也是通过子组件传给父组件,然后父组件调用子组件的方法。
父元素html
<div class="app-item">
<app-item-detail #appItemDetail></app-item-detail>
<app-item-detail2 (itemEvent)="addItem($event)"></app-item-detail2>
</div>
父元素ts
// 在父元素中获取子元素组件
@ViewChild('appItemDetail') appItemDetail: AppItemDetailConponent;
// 获取另一子组件@output传值
addItem(event) {
// 调用子元素的方法
this.appItemDetail.forchange(data)
}
3.组件关系--同在app中,毫无关系
例如头部有新消息提醒,在某个tab中点击确认后,头部消息也要置为已读。(只是场景,抛开websocket推送)
使用的是@Input和@Output的底层方法:Observables的subject方法。
MessageService服务
import {Injectable} from '@angular/core';
import {Subject} from 'rxjs';
@Injectable()
export class MessageService {
private user = new Subject();
user$ = this.user.asObservable();
changeUser(data) {
this.user.next(data);
}
}
传递消息的模块
// 引入服务
constructor(private msgService:MessageService)
// 调用传递消息的方法
this.msgService.changeUser('123');
接受消息的模块
// 引入服务
constructor(private msgService:MessageService)
// 获取传递的消息
this.msgService.user$.subscribe((data) => {
console.log(data);
})
优化写法:多次使用时,要在服务中定义多个变量,会导致服务臃肿。
export class MessageService {
private user = new Subject();
user$ = this.user.asObservable();
private permission = new Subject();
permission$ = this.permission.asObservable();
changeUser(data) {
this.user.next(data);
}
changePermission(data) {
this.permission.next(data);
}
}
优化写法:将所有使用变量存储到Map对象中
MessageService服务
import { Injectable } from '@angular/core';
import { Subject, Subscription } from 'rxjs';
@Injectable()
export class MessageService {
// 定义map接受需要变动的字段
private messageObservables = new Map<string, any>();
// 根据字段发送消息
Send(moduleId: string, message: any) {
this.getMessageObservable(moduleId).next(message);
}
// 定义字段并提供处理接受消息的方法
On(moduleId: string, observerOrNext?: any): Subscription {
return this.getMessageObservable(moduleId).subscribe(observerOrNext);
}
// 获取字段,从Map中获取,没有就创建
getMessageObservable(moduleId: string) {
let messageObservable = this.messageObservables.get(moduleId);
if (!messageObservable) {
messageObservable = new Subject();
this.messageObservables.set(moduleId, messageObservable);
}
return messageObservable;
}
}
传递消息的模块
// 引入服务
constructor(private msgService:MessageService)
// 调用传递消息的方法
this.msgService.Send('user','123');
this.msgService.Send('permission',{ a: 123 });
接受消息的模块
// 引入服务
constructor(private msgService:MessageService)
// 获取传递的消息
this.msgService.On('user', (data) => {
console.log(data);
})
// 获取传递的消息
this.msgService.On('permission', (data) => {
console.log(data);
})
因为是Map类型,key重复会被覆盖,使用时尽量避免。
消息传递目前就想到这些,后面有看到再补充。