※古い記事のため主にRxJSの説明になっています。共通データを管理したい場合はstoreを使いましょう。
Angularにて、アプリケーション全体で共通のデータを利用したいことなどがある。
例えばログインしているユーザーの情報など。
そこで共通データを管理するSharedDataService等を作る場合、
何も考えないと下記のようになると思う。
export class SharedDataService {
data: any;
constructor() {
data = {};
}
set(key: string, value: any) {
this.data[key] = value;
}
get(key: string) {
return this.data[key];
}
}
各コンポーネントからは下記のようにデータを取得。
const user = this.sharedDataService.get('user');
しかしこれはうまくいかない。
なぜかというと、だいたいログイン情報のようなものは非同期で取得して来ると思う。
その際にsetで値を保存すると思うが、その時はすでに各コンポーネントのonNgInit等も完了してしまっているし、
コンポーネントのプロパティに値を渡しているわけでもないので全体的に再描画はされない。
RxJSを使ってSharedDataService内のデータが変わったことを通知する仕組みにする必要がある。
export class SharedDataService {
data: any;
updateSources: any;
syncs: any;
constructor() {
data = {};
updateSources = {};
syncs = {};
}
set(key: string, value: any) {
this.data[key] = value;
if (this.updateSources[key]) {
this.updateSources[key].next(value);
}
}
sync(key: string, callback: (data: any)=>void) {
if (!this.syncs[key]) {
const updateSource = new Subject<any>();
this.updateSources[key] = updateSource;
this.syncs[key] = updateSource.asObservable();
}
this.syncs[key].subscribe(result => callback(result));
if (this.data[key] !== undefined) {
callback(this.data[key]);
}
}
}
データを取得する各コンポーネント側では下記のようにする。
this.sharedDataService.sync('user', user => this.user = user);
これでどこかで値がsetされる度に各コンポーネントの値が更新されて再描画されていく。
この仕組みを利用するとtitleタグなどの書き換えも簡単にできる。
setTitleはどうもAppComponent上でしか動作しないようなので、まずAppComponentにて
this.sharedDataService.sync('title', this.titleService.setTitle(title));
ルーティングの各コンポーネントで
this.sharedDataService.set('title', article.title);
そしてtitleをsetしていないページではtitleが元に戻るように、AppComponentにて
this.router.events.subscribe((event) => {
if (event instanceof NavigationStart) {
this.data.set('title', null);
}
});
これで指定したページでだけtitleが書き換えられる負担の少ない処理が可能となる。
ざっと作ったのでもしかするともうちょっと一般的なやり方があるかもしれないし、
構文も間違っている箇所があるかもしれない。
syncはコールバックの利用でなくObservableをそのままreturnした方が良いのかもしれない。
ただ、元々データが存在した場合はすぐ値がほしいので、
それを考慮するとコールバック形式である必要があるかもしれないしObservableでちゃんとしたやり方があるかもしれない。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント