Angular 这是阵列内存泄漏吗?

Angular 这是阵列内存泄漏吗?,angular,debugging,memory-leaks,google-chrome-devtools,Angular,Debugging,Memory Leaks,Google Chrome Devtools,正如您在所附图片中看到的,我正在调试以找出我的应用程序中的内存泄漏。 在“数组”项下有一个非常高的增量!“系统”,通过在主页(没有内容的地方)和图库之间切换20次,内存堆从6MB变为11MB。 ngrx调度和选择器用于库中,我使用异步管道将数据传递给库组件。我说的是gallery组件,因为通过排除它,对它进行评论,内存泄漏不再存在 首先,我想知道这是否真的是内存泄漏,如果是,我想知道如何消除它。既然这些是数组,那么它们不应该在组件销毁时被释放吗?那么“系统”三角洲呢?谢谢 上下文组件 @Com

正如您在所附图片中看到的,我正在调试以找出我的应用程序中的内存泄漏。
在“数组”项下有一个非常高的增量!“系统”,通过在主页(没有内容的地方)和图库之间切换20次,内存堆从6MB变为11MB。
ngrx调度和选择器用于库中,我使用异步管道将数据传递给库组件。我说的是gallery组件,因为通过排除它,对它进行评论,内存泄漏不再存在

首先,我想知道这是否真的是内存泄漏,如果是,我想知道如何消除它。既然这些是数组,那么它们不应该在组件销毁时被释放吗?那么“系统”三角洲呢?谢谢

上下文组件

@Component({
    selector: 'app-conteiner-gallery',
    template:`
        <app-gallery [allCars]="allCars$ | async" 
                    [brands]="brands$ | async" 
                    [types]="types$ | async" 
                    [usersRatings]="usersRatings$ | async" 
                    [recentSeenCars]="recentSeenCars$ | async"
                    [observedCars]="observedCars$ | async"
                    
                    (setObservedCarAction)="onSetObservedCar($event)"
                    (setNotObservedCarAction)="onSetNotObservedCar($event)"
                    (setObservedCarsAction)="onSetObservedCars($event)"
                    (setBrandChecked)="onSetBrandChecked($event)"
                    (setBrandsChecked)="onSetBrandsChecked($event)"
                    (setTypeChecked)="onSetTypeChecked($event)"
                    (setTypesChecked)="onSetTypesChecked($event)">
        </app-gallery>
    `
})

export class ConteinerGalleryComponent implements OnInit, OnDestroy{

    allCars$:Observable<Car[]>
    brands$:Observable<BrandCB[]>
    types$:Observable<TypeCB[]>
    usersRatings$:Observable<UserRating[]>
    recentSeenCars$:Observable<RecentSeenCar[]>
    observedCars$:Observable<ObservedCar[]>

    unsubscription$:Subject<boolean> = new Subject

    isStoreLoaded:boolean = false
    isStoreRecentSeenCarsLoaded:boolean = false

    constructor( private store:Store<StoreState>, private authService:AuthenticationService){}

    ngOnDestroy():void{
        this.unsubscription$.next(true)
        this.unsubscription$.complete()
    }

    ngOnInit(): void {

        this.store.pipe(select(statusSelectors.isStoreLoaded))
            .pipe( takeUntil(this.unsubscription$))
            .subscribe( loaded => this.isStoreLoaded = loaded)

        this.store.pipe(select(statusSelectors.isRecentSeenCarsLoaded))
            .pipe(takeUntil(this.unsubscription$))
            .subscribe( loaded => this.isStoreRecentSeenCarsLoaded = loaded)

        !this.isStoreLoaded ? this.store.dispatch(carsActions.getAllCars()) : null
        !this.isStoreLoaded ? this.store.dispatch(brandsActions.getBrands()) : null
        !this.isStoreLoaded ? this.store.dispatch(typesActions.getTypes()) : null
        !this.isStoreLoaded ? this.store.dispatch(userRatingsActions.getUsersRatings()) : null

        if(!this.isStoreRecentSeenCarsLoaded && this.authService.currentUserValue){
            this.store.dispatch(recentSeenCarsActions.getRecentSeenCars())
            this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:true}))
        }

        if(!this.isStoreLoaded)
            this.authService.currentUserValue ? this.store.dispatch(observedCarsActions.getObservedCars()) : null

        this.store.dispatch(statusActions.setStoreLoaded({loaded:true}))

        this.allCars$ = this.store.pipe(select(carsSelectors.getAllCars))
           
        this.brands$ = this.store.pipe(select(brandsSelectors.getBrands))
            
        this.types$ = this.store.pipe(select(typeSelectors.getTypes))
        
        this.usersRatings$ = this.store.pipe(select(userRatingsSelectors.getUsersRatings))

        this.recentSeenCars$ = this.store.pipe(select(userRecentSeenCarsSelectors.getUsers))

        this.observedCars$ = this.store.pipe(select(userObservedCarsSelectors.getUsers))
            
    }

    onSetObservedCar(carId:number):void{
        let observed:ObservedCar = {id:null, carId:carId, userId:null}
        this.store.dispatch(observedCarsActions.setObservedCar({carId}))
    }

    onSetNotObservedCar(carId:number):void{
        this.store.dispatch(observedCarsActions.setNotObservedCar({carId}))
    }

    onSetObservedCars(cars:Car[]):void{
        this.store.dispatch(carsActions.setCarsWithObserved({cars}))
    }

    onSetBrandChecked(brand:BrandCB):void{
        this.store.dispatch(brandsActions.setBrandChecked({brand}))
    }

    onSetBrandsChecked(brands:BrandCB[]):void{
        this.store.dispatch(brandsActions.setBrandsChecked({brands}))
    }

    onSetTypeChecked(typee:TypeCB):void{
        this.store.dispatch(typesActions.setTypeChecked({typee}))
    }

    onSetTypesChecked(types:TypeCB[]):void{
        this.store.dispatch(typesActions.setTypesChecked({types}))
    }

    public logout():void{
        this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:false}))
    }
}
export class GalleryComponent implements OnInit, DoCheck, OnChanges{

    @Input() allCars:Car[]
    @Input() brands:BrandCB[]
    @Input() types:TypeCB[]
    @Input() usersRatings:UserRating[]
    @Input() recentSeenCars:Car[]
    @Input() observedCars:ObservedCar[]

    @Output() setObservedCarAction = new EventEmitter<any>()
    @Output() setNotObservedCarAction = new EventEmitter<any>()
    @Output() setObservedCarsAction = new EventEmitter<any>()
    @Output() setBrandCount = new EventEmitter<any>()
    @Output() setTypeCount = new EventEmitter<any>()
    @Output() setBrandChecked = new EventEmitter<any>()
    @Output() setTypeChecked = new EventEmitter<any>()
    @Output() setBrandsChecked = new EventEmitter<any>()
    @Output() setTypesChecked = new EventEmitter<any>()

    filteredCars:Car[] = []
/*     brandsCB:BrandCB[] = []
    typesCB:TypeCB[] = [] */

    user:User

    iterableDiffer:IterableDiffer<any>

    checkboxBrandAll:boolean = true
    checkboxTypeAll:boolean = true

    leftConteinerClass:string

    faBars = faBars

    constructor( private authService:AuthenticationService, private iterableDiffers: IterableDiffers){
        this.iterableDiffer = iterableDiffers.find([]).create(null);
    }

    // evocata quando ci sono cambiamenti nelle proprietà di input
    ngOnChanges(changes: SimpleChanges): void {
        // c'è bisogno di chiamare filterCars perchè oltre a filtrare le auto aggiorna l'array in visualizzazione
        changes.allCars ? this.filterCars(this.brands, this.types) : null        
    }

    ngDoCheck(): void {
        // used when observed buttons are pressed
        let changes = this.iterableDiffer.diff(this.observedCars);
        if (changes) {
            this.user ? this.setObservedCars() : null
        }

    }

    ngOnInit():void{
        this.user = this.authService.currentUserValue
        this.user ? this.setObservedCars() : null
        this.initFilters()
        this.filterCars(this.brands, this.types)

        this.showNormalLeftConteiner()
        window.addEventListener('resize', () => this.showNormalLeftConteiner())
    }

    // setta le checkbox degli "all" dei filtri a false se altre checkbox risultano selezionate
    initFilters(){
        let filtersBrands:boolean = false
        let filtersTypes:boolean = false
        this.brands.some( brand => brand.checked) ? filtersBrands = true : null
        this.types.some( type => type.checked) ? filtersTypes = true : null

        filtersBrands ? this.checkboxBrandAll = false : null
        filtersTypes ? this.checkboxTypeAll = false : null
    }

    // operazioni da effettuara al cambiamento di una checkbox dei filtri.
    checkboxChange(event, brand, type):void{

        let name = event.target.name;
        let checked = event.target.checked;
        
        let brands:BrandCB[] = JSON.parse(JSON.stringify(this.brands))
        let types:TypeCB[] = JSON.parse(JSON.stringify(this.types))

        //BRANDS
        if(name =='allBrands'){

            if(checked == true){
        
                brands.map(brand => brand.checked = false);

                this.checkboxBrandAll = true

                this.filterCars(brands, types)
                brands = this.countBrands(brands)
                types = this.countTypes(types)
                this.setBrandsChecked.emit(brands)
                this.setTypesChecked.emit(types)
            
            }else{
                this.checkboxBrandAll = true
            }


        } else if(name == 'otherBrands'){

            brands = brands.map( b => {
                if(b.id == brand.id){
                    return ({...brand, checked:checked})
                }else{
                    return b
                }
            })

            if(checked == true){

                this.checkboxBrandAll = false;
              
            }else
                brands.some( b => b.checked) ? null : this.checkboxBrandAll = true

            this.filterCars(brands, types)
            brands = this.countBrands(brands)
            types = this.countTypes(types)
            this.setBrandsChecked.emit(brands)
            this.setTypesChecked.emit(types)
        
        }

        // TYPES        
        if(name =='allTypes'){

            if(checked == true){

                types.map(type => type.checked = false)

                this.checkboxTypeAll = true
            
                this.filterCars(brands, types)
                brands = this.countBrands(brands)
                types = this.countTypes(types)
                this.setBrandsChecked.emit(brands)
                this.setTypesChecked.emit(types)

            }else{
                this.checkboxTypeAll = true
            }

        } else if(name == 'otherTypes'){

            types = types.map( t => {
                if(t.id == type.id){
                    return ({...type, checked:checked})
                }else{
                    return t
                }
            })

            if(checked == true){

                this.checkboxTypeAll = false;

            }else
                types.some( t => t.checked) ? null : this.checkboxTypeAll = true

            this.filterCars(brands, types)
            brands = this.countBrands(brands)
            types = this.countTypes(types)
            this.setBrandsChecked.emit(brands)
            this.setTypesChecked.emit(types)

        }

    }

    // aggiorna la proprietà "observed" di allCars
    setObservedCars():void{
        let allCars:Car[] = JSON.parse(JSON.stringify(this.allCars))
        let observedCars:ObservedCar[] = [...this.observedCars]

        allCars.map( car => {
            // se la car è osservata, setta "observed" a true
            observedCars.some( obs => obs.carId == car.id) ? car.observed = true : car.observed = false

        })

        this.setObservedCarsAction.emit(allCars)

    }

    // aggiorna l array per la gallery (this.filteredCars) con l'array modificato eventualmente nei filtri o nella proprietà observed (this.allCars)
    filterCars(brands:BrandCB[], types:TypeCB[]):void{

        let allCars = [...this.allCars];
        
        const checkedBrands = brands.filter(brand => brand.checked);
        const checkedTypes = types.filter(type => type.checked);

        let filteredCars:Car[];

        if(!this.checkboxBrandAll && !this.checkboxTypeAll){

            filteredCars = allCars.filter(car => checkedBrands.find(brand => brand.name === car.brand) && checkedTypes.find(type => type.name === car.type));

        } else if(!this.checkboxBrandAll && this.checkboxTypeAll){

            filteredCars = allCars.filter(car => checkedBrands.find(brand => brand.name === car.brand));
        
        }else if(this.checkboxBrandAll && !this.checkboxTypeAll){
        
            filteredCars = allCars.filter(car => checkedTypes.find(type => type.name ===car.type));

        }else{

            filteredCars = [...allCars];
        
        }

        this.filteredCars = [...filteredCars]

    }
 
    // conta le occorrenze di ogni brand, ad esempio ferrari(2)
    countBrands(brands:BrandCB[]):BrandCB[]{

        let br:BrandCB[] = brands.map( brand => {
            
            let count = 0;
            
            this.filteredCars.forEach( car => {
                brand.name == car.brand ? count++ : null
            })
            
            brand.count = count;

            return brand
        
        })
        
        return br
    
    }

    // conta le occorrenze di ogni type, ad esempio jeep(2)
    countTypes(types:TypeCB[]):TypeCB[]{

        let ty:TypeCB[] = types.map( type => {

            let count = 0;
            
            this.filteredCars.forEach( car => {
                type.name == car.type ? count++ : null
            
            })
            
            type.count = count;

            return type
        })

        return ty
    
    }

    showMobileLeftConteiner():void{
        this.leftConteinerClass = 'show-mobile-left-conteiner'
    }

    showNormalLeftConteiner():void{
        if(window.innerWidth >= 1051){
            this.leftConteinerClass = 'show-normal-left-conteiner'
        }else{
            this.hideLeftContenier()
        }
    }

    hideLeftContenier():void{
        this.leftConteinerClass = 'hide-left-conteiner'
    }

    onSetObservedCar(carId:number):void{
        this.setObservedCarAction.emit(carId)
    }

    onSetNotObservedCar(carId:number):void{
        this.setNotObservedCarAction.emit(carId)
    }

}
@组件({
选择器:“应用程序上下文库”,
模板:`
`
})
导出类ConteinerGalleryComponent实现OnInit、OnDestroy{
allCars$:可观察
品牌美元:可观察
类型$:可观察
usersRatings$:可观察
近期SEENCARS$:可观测
观测车辆$:可观测
退订$:科目=新科目
isStoreLoaded:boolean=false
isStoreRecentSeenCarsLoaded:boolean=false
构造函数(私有存储:存储,私有authService:AuthenticationService){}
ngOnDestroy():void{
此.unsubscription$.next(true)
此.unsubscription$.complete()
}
ngOnInit():void{
this.store.pipe(选择(statusSelectors.isStoreLoaded))
.pipe(takeUntil(此.unsubscription$))
.subscribe(已加载=>this.isStoreLoaded=已加载)
this.store.pipe(选择(statusSelectors.isRecentSeenCarsLoaded))
.pipe(takeUntil(此.unsubscription$))
.subscribe(已加载=>this.isStoreRecentSeenCarsLoaded=已加载)
!this.isStoreLoaded?this.store.dispatch(carsActions.getAllCars()):null
!this.isStoreLoaded?this.store.dispatch(brandsActions.getBrands()):null
!this.isStoreLoaded?this.store.dispatch(typesActions.getTypes()):null
!this.isStoreLoaded?this.store.dispatch(userRatingsActions.getUsersRatings()):null
如果(!this.isStoreRecentSeenCarsLoaded&&this.authService.currentUserValue){
this.store.dispatch(recentSeencarActions.getRecentSeenCars())
this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:true}))
}
如果(!this.isStoreLoaded)
this.authService.currentUserValue?this.store.dispatch(observedCarsActions.getObservedCars()):null
this.store.dispatch(statusActions.setStoreLoaded({loaded:true}))
this.allCars$=this.store.pipe(选择(carsselector.getAllCars))
this.brands$=this.store.pipe(选择(brandsSelectors.getBrands))
this.types$=this.store.pipe(select(typeSelectors.getTypes))
this.usersRatings$=this.store.pipe(选择(userratingsselector.getUsersRatings))
this.recentSeenCars$=this.store.pipe(选择(userRecentSeenCarsSelectors.getUsers))
this.observedCars$=this.store.pipe(选择(userObservedCarsSelectors.getUsers))
}
onSetObservedCar(carId:编号):无效{
let ObservedCar={id:null,carId:carId,userId:null}
this.store.dispatch(observedCarsActions.setObservedCar({carId}))
}
onSetNotObservedCar(carId:编号):无效{
this.store.dispatch(observedCarsActions.setNotObservedCar({carId}))
}
onSetObservedCars(cars:Car[]):无效{
this.store.dispatch(carsActions.setCarsWithObserved({cars}))
}
onSetBrandChecked(品牌:BrandCB):无效{
this.store.dispatch(brandsActions.setBrandChecked({brand}))
}
onSetBrandsChecked(品牌:BrandCB[]):无效{
this.store.dispatch(brandsActions.setBrandsChecked({brands}))
}
onSetTypeChecked(类型E:TypeCB):无效{
this.store.dispatch(typesActions.setTypeChecked({typee}))
}
onSetTypesChecked(类型:TypeCB[]):void{
this.store.dispatch(typesActions.setTypesChecked({types}))
}
公共注销():无效{
this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:false}))
}
}
库组件

@Component({
    selector: 'app-conteiner-gallery',
    template:`
        <app-gallery [allCars]="allCars$ | async" 
                    [brands]="brands$ | async" 
                    [types]="types$ | async" 
                    [usersRatings]="usersRatings$ | async" 
                    [recentSeenCars]="recentSeenCars$ | async"
                    [observedCars]="observedCars$ | async"
                    
                    (setObservedCarAction)="onSetObservedCar($event)"
                    (setNotObservedCarAction)="onSetNotObservedCar($event)"
                    (setObservedCarsAction)="onSetObservedCars($event)"
                    (setBrandChecked)="onSetBrandChecked($event)"
                    (setBrandsChecked)="onSetBrandsChecked($event)"
                    (setTypeChecked)="onSetTypeChecked($event)"
                    (setTypesChecked)="onSetTypesChecked($event)">
        </app-gallery>
    `
})

export class ConteinerGalleryComponent implements OnInit, OnDestroy{

    allCars$:Observable<Car[]>
    brands$:Observable<BrandCB[]>
    types$:Observable<TypeCB[]>
    usersRatings$:Observable<UserRating[]>
    recentSeenCars$:Observable<RecentSeenCar[]>
    observedCars$:Observable<ObservedCar[]>

    unsubscription$:Subject<boolean> = new Subject

    isStoreLoaded:boolean = false
    isStoreRecentSeenCarsLoaded:boolean = false

    constructor( private store:Store<StoreState>, private authService:AuthenticationService){}

    ngOnDestroy():void{
        this.unsubscription$.next(true)
        this.unsubscription$.complete()
    }

    ngOnInit(): void {

        this.store.pipe(select(statusSelectors.isStoreLoaded))
            .pipe( takeUntil(this.unsubscription$))
            .subscribe( loaded => this.isStoreLoaded = loaded)

        this.store.pipe(select(statusSelectors.isRecentSeenCarsLoaded))
            .pipe(takeUntil(this.unsubscription$))
            .subscribe( loaded => this.isStoreRecentSeenCarsLoaded = loaded)

        !this.isStoreLoaded ? this.store.dispatch(carsActions.getAllCars()) : null
        !this.isStoreLoaded ? this.store.dispatch(brandsActions.getBrands()) : null
        !this.isStoreLoaded ? this.store.dispatch(typesActions.getTypes()) : null
        !this.isStoreLoaded ? this.store.dispatch(userRatingsActions.getUsersRatings()) : null

        if(!this.isStoreRecentSeenCarsLoaded && this.authService.currentUserValue){
            this.store.dispatch(recentSeenCarsActions.getRecentSeenCars())
            this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:true}))
        }

        if(!this.isStoreLoaded)
            this.authService.currentUserValue ? this.store.dispatch(observedCarsActions.getObservedCars()) : null

        this.store.dispatch(statusActions.setStoreLoaded({loaded:true}))

        this.allCars$ = this.store.pipe(select(carsSelectors.getAllCars))
           
        this.brands$ = this.store.pipe(select(brandsSelectors.getBrands))
            
        this.types$ = this.store.pipe(select(typeSelectors.getTypes))
        
        this.usersRatings$ = this.store.pipe(select(userRatingsSelectors.getUsersRatings))

        this.recentSeenCars$ = this.store.pipe(select(userRecentSeenCarsSelectors.getUsers))

        this.observedCars$ = this.store.pipe(select(userObservedCarsSelectors.getUsers))
            
    }

    onSetObservedCar(carId:number):void{
        let observed:ObservedCar = {id:null, carId:carId, userId:null}
        this.store.dispatch(observedCarsActions.setObservedCar({carId}))
    }

    onSetNotObservedCar(carId:number):void{
        this.store.dispatch(observedCarsActions.setNotObservedCar({carId}))
    }

    onSetObservedCars(cars:Car[]):void{
        this.store.dispatch(carsActions.setCarsWithObserved({cars}))
    }

    onSetBrandChecked(brand:BrandCB):void{
        this.store.dispatch(brandsActions.setBrandChecked({brand}))
    }

    onSetBrandsChecked(brands:BrandCB[]):void{
        this.store.dispatch(brandsActions.setBrandsChecked({brands}))
    }

    onSetTypeChecked(typee:TypeCB):void{
        this.store.dispatch(typesActions.setTypeChecked({typee}))
    }

    onSetTypesChecked(types:TypeCB[]):void{
        this.store.dispatch(typesActions.setTypesChecked({types}))
    }

    public logout():void{
        this.store.dispatch(statusActions.setRecentSeenCarsLoaded({loaded:false}))
    }
}
export class GalleryComponent implements OnInit, DoCheck, OnChanges{

    @Input() allCars:Car[]
    @Input() brands:BrandCB[]
    @Input() types:TypeCB[]
    @Input() usersRatings:UserRating[]
    @Input() recentSeenCars:Car[]
    @Input() observedCars:ObservedCar[]

    @Output() setObservedCarAction = new EventEmitter<any>()
    @Output() setNotObservedCarAction = new EventEmitter<any>()
    @Output() setObservedCarsAction = new EventEmitter<any>()
    @Output() setBrandCount = new EventEmitter<any>()
    @Output() setTypeCount = new EventEmitter<any>()
    @Output() setBrandChecked = new EventEmitter<any>()
    @Output() setTypeChecked = new EventEmitter<any>()
    @Output() setBrandsChecked = new EventEmitter<any>()
    @Output() setTypesChecked = new EventEmitter<any>()

    filteredCars:Car[] = []
/*     brandsCB:BrandCB[] = []
    typesCB:TypeCB[] = [] */

    user:User

    iterableDiffer:IterableDiffer<any>

    checkboxBrandAll:boolean = true
    checkboxTypeAll:boolean = true

    leftConteinerClass:string

    faBars = faBars

    constructor( private authService:AuthenticationService, private iterableDiffers: IterableDiffers){
        this.iterableDiffer = iterableDiffers.find([]).create(null);
    }

    // evocata quando ci sono cambiamenti nelle proprietà di input
    ngOnChanges(changes: SimpleChanges): void {
        // c'è bisogno di chiamare filterCars perchè oltre a filtrare le auto aggiorna l'array in visualizzazione
        changes.allCars ? this.filterCars(this.brands, this.types) : null        
    }

    ngDoCheck(): void {
        // used when observed buttons are pressed
        let changes = this.iterableDiffer.diff(this.observedCars);
        if (changes) {
            this.user ? this.setObservedCars() : null
        }

    }

    ngOnInit():void{
        this.user = this.authService.currentUserValue
        this.user ? this.setObservedCars() : null
        this.initFilters()
        this.filterCars(this.brands, this.types)

        this.showNormalLeftConteiner()
        window.addEventListener('resize', () => this.showNormalLeftConteiner())
    }

    // setta le checkbox degli "all" dei filtri a false se altre checkbox risultano selezionate
    initFilters(){
        let filtersBrands:boolean = false
        let filtersTypes:boolean = false
        this.brands.some( brand => brand.checked) ? filtersBrands = true : null
        this.types.some( type => type.checked) ? filtersTypes = true : null

        filtersBrands ? this.checkboxBrandAll = false : null
        filtersTypes ? this.checkboxTypeAll = false : null
    }

    // operazioni da effettuara al cambiamento di una checkbox dei filtri.
    checkboxChange(event, brand, type):void{

        let name = event.target.name;
        let checked = event.target.checked;
        
        let brands:BrandCB[] = JSON.parse(JSON.stringify(this.brands))
        let types:TypeCB[] = JSON.parse(JSON.stringify(this.types))

        //BRANDS
        if(name =='allBrands'){

            if(checked == true){
        
                brands.map(brand => brand.checked = false);

                this.checkboxBrandAll = true

                this.filterCars(brands, types)
                brands = this.countBrands(brands)
                types = this.countTypes(types)
                this.setBrandsChecked.emit(brands)
                this.setTypesChecked.emit(types)
            
            }else{
                this.checkboxBrandAll = true
            }


        } else if(name == 'otherBrands'){

            brands = brands.map( b => {
                if(b.id == brand.id){
                    return ({...brand, checked:checked})
                }else{
                    return b
                }
            })

            if(checked == true){

                this.checkboxBrandAll = false;
              
            }else
                brands.some( b => b.checked) ? null : this.checkboxBrandAll = true

            this.filterCars(brands, types)
            brands = this.countBrands(brands)
            types = this.countTypes(types)
            this.setBrandsChecked.emit(brands)
            this.setTypesChecked.emit(types)
        
        }

        // TYPES        
        if(name =='allTypes'){

            if(checked == true){

                types.map(type => type.checked = false)

                this.checkboxTypeAll = true
            
                this.filterCars(brands, types)
                brands = this.countBrands(brands)
                types = this.countTypes(types)
                this.setBrandsChecked.emit(brands)
                this.setTypesChecked.emit(types)

            }else{
                this.checkboxTypeAll = true
            }

        } else if(name == 'otherTypes'){

            types = types.map( t => {
                if(t.id == type.id){
                    return ({...type, checked:checked})
                }else{
                    return t
                }
            })

            if(checked == true){

                this.checkboxTypeAll = false;

            }else
                types.some( t => t.checked) ? null : this.checkboxTypeAll = true

            this.filterCars(brands, types)
            brands = this.countBrands(brands)
            types = this.countTypes(types)
            this.setBrandsChecked.emit(brands)
            this.setTypesChecked.emit(types)

        }

    }

    // aggiorna la proprietà "observed" di allCars
    setObservedCars():void{
        let allCars:Car[] = JSON.parse(JSON.stringify(this.allCars))
        let observedCars:ObservedCar[] = [...this.observedCars]

        allCars.map( car => {
            // se la car è osservata, setta "observed" a true
            observedCars.some( obs => obs.carId == car.id) ? car.observed = true : car.observed = false

        })

        this.setObservedCarsAction.emit(allCars)

    }

    // aggiorna l array per la gallery (this.filteredCars) con l'array modificato eventualmente nei filtri o nella proprietà observed (this.allCars)
    filterCars(brands:BrandCB[], types:TypeCB[]):void{

        let allCars = [...this.allCars];
        
        const checkedBrands = brands.filter(brand => brand.checked);
        const checkedTypes = types.filter(type => type.checked);

        let filteredCars:Car[];

        if(!this.checkboxBrandAll && !this.checkboxTypeAll){

            filteredCars = allCars.filter(car => checkedBrands.find(brand => brand.name === car.brand) && checkedTypes.find(type => type.name === car.type));

        } else if(!this.checkboxBrandAll && this.checkboxTypeAll){

            filteredCars = allCars.filter(car => checkedBrands.find(brand => brand.name === car.brand));
        
        }else if(this.checkboxBrandAll && !this.checkboxTypeAll){
        
            filteredCars = allCars.filter(car => checkedTypes.find(type => type.name ===car.type));

        }else{

            filteredCars = [...allCars];
        
        }

        this.filteredCars = [...filteredCars]

    }
 
    // conta le occorrenze di ogni brand, ad esempio ferrari(2)
    countBrands(brands:BrandCB[]):BrandCB[]{

        let br:BrandCB[] = brands.map( brand => {
            
            let count = 0;
            
            this.filteredCars.forEach( car => {
                brand.name == car.brand ? count++ : null
            })
            
            brand.count = count;

            return brand
        
        })
        
        return br
    
    }

    // conta le occorrenze di ogni type, ad esempio jeep(2)
    countTypes(types:TypeCB[]):TypeCB[]{

        let ty:TypeCB[] = types.map( type => {

            let count = 0;
            
            this.filteredCars.forEach( car => {
                type.name == car.type ? count++ : null
            
            })
            
            type.count = count;

            return type
        })

        return ty
    
    }

    showMobileLeftConteiner():void{
        this.leftConteinerClass = 'show-mobile-left-conteiner'
    }

    showNormalLeftConteiner():void{
        if(window.innerWidth >= 1051){
            this.leftConteinerClass = 'show-normal-left-conteiner'
        }else{
            this.hideLeftContenier()
        }
    }

    hideLeftContenier():void{
        this.leftConteinerClass = 'hide-left-conteiner'
    }

    onSetObservedCar(carId:number):void{
        this.setObservedCarAction.emit(carId)
    }

    onSetNotObservedCar(carId:number):void{
        this.setNotObservedCarAction.emit(carId)
    }

}
导出类GalleryComponent实现OnInit、DoCheck和OnChanges{
@输入()所有汽车:汽车[]
@输入()品牌:BrandCB[]
@Input()类型:TypeCB[]
@Input()usersRatings:UserRating[]
@Input()recentSeenCars:Car[]
@Input()observedCars:observedCars[]
@Output()setObservedCarAction=新的EventEmitter()
@Output()setNotObservedCarAction=new EventEmitter()
@Output()setObservedCarsAction=new EventEmitter()
@Output()setBrandCount=新的EventEmitter()
@Output()setTypeCount=新的EventEmitter()
@Output()setBrandChecked=neweventemitter()
@Output()setTypeChecked=neweventemitter()
@Output()setBrandsChecked=neweventemitter()
@Output()setTypesChecked=新的EventEmitter()
过滤卡:汽车[]=[]
/*brandsCB:BrandCB[]=[]
类型Cb:TypeCB[]=[]*/
用户:用户
iterableDiffer:iterableDiffer
checkboxBrandAll:boolean=true
checkboxTypeAll:boolean=true
LeftContentinerClass:字符串
faBars=faBars
构造函数(私有authService:AuthenticationService,私有iterableDiffers:iterableDiffers){
this.iterableDiffer=iterableDiffer.find([]).create(null);
}
//evocata quando ci sono cambiamenti nelle proprietádi input
ngOnChanges(更改:SimpleChanges):无效{
//c'bisogno di chiamare filterCars在Visualizazione中安装了一个过滤自动聚集数组
changes.allCars?this.filterCars(this.brands,this.types):null
}
ngDoCheck():void{
//按下观察按钮时使用
让changes=this.iterableDiffer.diff(this.observedCa