私のアプリには、「フィルター」と「ホーム」という2つのコンポーネントがあります。これら2つのコンポーネントは、アプリコンポーネントの子コンポーネントです。
サービスを介してフィルターコンポーネントからホームコンポーネントに渡したいタイプの以下のオブジェクトがあります。また、フィルターコンポーネントで変更されるたびにこのデータをホームコンポーネントで更新するため、BehaviorSubjectをサービスで使用します。
モデル:filter-response.model.ts
export interface FilterResponse{
filter:string;
filterlist:string[];
}
filter.component.ts
export class FilterComponent implements OnInit {
filterMainList:FilterResponse[]=[
{
"filter": "abc",
"filterlist": ["a","b","c"]
},
{
"filter": "def",
"filterlist":["d","e","f"]
},
{
"filter": "ghi",
"filterlist": ["g","h","i"]
}
];
constructor(private filterService:FilterService,) {
this.filterService.setFilterConditions(this.filterMainList);
}
ngOnInit() {
}
}
ホームコンポーネントでデータを受信しましたが、データに変更を加えたいと考えています。
home.component.ts
export class HomeComponent implements OnInit {
constructor(private filterService:FilterService) {
this.filterService.getFilterConditions().subscribe((data)=>{
let tc:FilterResponse[]=data
for(let f in tc){
tc[f].filterlist=['changes'];//this is where I make the changes
}
});
}
ngOnInit() {
}
}
振る舞い主体のフィルターサービスを持っています。これは私が混乱したところです。 next()の前にサービスのデータをここに記録します。実際にここに表示されるデータは、ホームコンポーネントで変更したものです。つまり、ホームコンポーネントのデータのインスタンスで行った変更も、インスタンスのインスタンスに影響(変更)しています。稼働中のデータ。
filter.service.ts
@Injectable({
providedIn:'root'
})
export class FilterService{
private filterConditions = new BehaviorSubject<FilterResponse[]>(null);
constructor(){}
setFilterConditions(filterList:FilterResponse[]){
console.log(filterList);//data changes incorrectly
this.filterConditions.next(filterList);
}
getFilterConditions():Observable<FilterResponse[]>{
return this.filterConditions.asObservable();
}
}
私のコンソールログ:
実際にフィルターコンポーネントに渡したデータであるはずのデータ。しかし、ホームコンポーネントで変更したデータが表示されます。
そして最後にapp.component.ts、それが役立つ場合
app.component.ts
<app-filter></app-filter>
<app-home></app-home>
もう1つ、お知らせしたいことがあります。 Stackblitzでシナリオを再現してみました。しかし、ひねりはそれがそこでうまく機能していることです。
https://stackblitz.com/edit/angular-ivy-9th5pj
私のプロジェクトで欠けているものを親切に説明してください。または、これはサービスが角度で機能する実際の方法ですか?.
私はクッシュの答えを拡張します。したがって、ディープコピーを作成しても何も機能しない場合は、loadashからcloneDeep関数を使用できます。このオプションは最悪の場合に使用してください(修正プログラムの問題)。この問題は、浅いコピーが原因で発生します。したがって、それぞれの場合に配列を返すときは、新しい配列ではなく配列のアドレスを返します。したがって、配列に変更が発生すると、元の配列に変更が発生します。そして、JSON.stringigyまたはdeepClone関数を使用すると、内部的に異なるアドレスで配列のコピーを作成します
setFilterConditions(filterList:FilterResponse[]){
this.filterConditions.next(cloneDeep(filterList));
}