Angular 4组件内部动画实现

5

我有一个关于同一组件路由动画的问题。例如,我有以下路由:

{path: 'product/category/:category', component: CategoryComponent},

首先,我解决了路由参数的问题,因为当我在相同的组件之间导航时,它们不会刷新ngOnit()函数。但现在我已经向我的应用程序添加了动画,如果我从HomeComponent到CategoryComponent,它可以完美地工作。但是如果我带着不同的参数从CategoryComponent到CategoryComponent,动画就不起作用了。

这是我的动画文件:

import { animate, AnimationEntryMetadata, state, style, transition, trigger } from '@angular/core';

// Component transition animations
export const slideInDownAnimation: AnimationEntryMetadata =
  trigger('routeAnimation', [
    state('*',
      style({
        opacity: 1,
        transform: 'translateX(0)'
      })
    ),
    transition(':enter', [
      style({
        opacity: 0,
        transform: 'translateX(-100%)'
      }),
      animate('0.5s ease-in')
    ]),
    transition(':leave', [
      animate('0.5s ease-out', style({
        opacity: 0,
        transform: 'translateY(100%)'
      }))
    ])
  ]);

以下是我的CategoryComponent.ts代码:

import { Component, OnInit, EventEmitter,Input, Output,HostBinding} from '@angular/core';
import { Pipe, PipeTransform } from '@angular/core';

import {FirebaseService} from '../../services/firebase.service';
import { AngularFireDatabase, FirebaseListObservable,FirebaseObjectObservable} from 'angularfire2/database';
import {Router, ActivatedRoute, Params,ParamMap} from '@angular/router';
import * as firebase from 'firebase';
import { Observable } from 'rxjs';
import {Subject} from 'rxjs';
import { routerTransition } from '../../router.animations';
import { slideInDownAnimation } from '../../animations';

import { FlashMessagesService } from 'angular2-flash-messages';
@Component({   
  host: {
     '[@routeAnimation]': 'true'
   },
  selector: 'app-category',
  templateUrl: './category.component.html',  
  styleUrls: ['./category.component.css'],  
  animations: [ slideInDownAnimation ]
})
export class CategoryComponent implements OnInit {
  @HostBinding('@routeAnimation') routeAnimation = true;
  @HostBinding('style.display')   display = 'block';
  @HostBinding('style.position')  position = 'absolute';
  products:any;
  search:any;
  imageUrls:any = [];
  imgSelected: any;
  counter:any;
  image:any;
  images:any;
  myimage:any;
  count:any;
  sub:any;  
  i:any;
  category:any;
  fakeimage:any;  
  constructor(
    private firebaseService: FirebaseService,
    private router:Router,
    public af:AngularFireDatabase,
    private route:ActivatedRoute,    
    private flashMessage:FlashMessagesService) {


  }

ngOnInit() {

    this.counter = 0; 

    var params;
    this.sub = this.route.paramMap
      .switchMap((params: ParamMap) =>
      this.firebaseService.getProductsByCategory(params.get('category'))).subscribe(products => {
      this.products = products;
      this.count = products.length;
    });;


 }

  returnImage(key,url){
   this.imageUrls.push(new ImageUrl(key,url));
  }
  searchProps(){    
    this.firebaseService.getProductsByTitle(this.search.toLowerCase()).subscribe(products => { 
      this.products = products;
    });
  }

getProductsByTitle(title){
  console.log('here');    
    this.firebaseService.getProductsByTitle(title.toLowerCase()).subscribe(products => { 
      this.products = products;
    }); 

}
getImageUrl(prodid) {
        // Go call api to get poster.  
        var data = ''; 
        var that = this;
        this.firebaseService.getProductImages(prodid).subscribe(images => { 
          this.image = images[0];
          var img = this.image;
          if(this.image != null){
            let storageRef = firebase.storage().ref();
            let spaceRef = storageRef.child(this.image.path);
            storageRef.child(img.path).getDownloadURL().then(function(url) {
              that.returnImage(img.$key,url);

              }).catch(function(error) {
                // Handle any errors
              });
          }             
        });
}
  ngOnDestroy() {
    this.sub.unsubscribe();
  }

}
export class ImageUrl {
  url: string;
  id:string;
  constructor(public _id:string,public _url: string) {

  }
}

你有什么想法可以在这里做吗?

谢谢。

2个回答

4
你可以像这样添加路由复用策略:
import { ActivatedRouteSnapshot, RouteReuseStrategy, DetachedRouteHandle } from '@angular/router';

export class CustomReuseStrategy implements RouteReuseStrategy {

    shouldDetach(route: ActivatedRouteSnapshot): boolean {
        return false;
    }

    store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): boolean {
        return false;
    }

    shouldAttach(route: ActivatedRouteSnapshot): boolean {
        return false;        
    }

    retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        return false;
    }

    shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        return false;
    }    
}

然后将其作为提供者导入您的模块:

providers: [
    {provide: RouteReuseStrategy, useClass: CustomReuseStrategy}
],

这将导致每次路由参数更改时都会触发ngOnInit。在我的一个应用程序中,我将此策略用作我的页面转换的一部分。我写了一篇关于如何设置它的文章,网址是https://justabill.blog/angular-5-router-animations-tied-to-images-loading/


3

您说得一点也没错。当从一个路由参数转到使用相同组件的另一个路由参数时,ngOnInit不会再次触发;只有内容被交换。

路由器是按照这种方式设计的,即使路由参数发生变化,也要使用相同的组件实例。

Github上有一个主题(https://github.com/angular/angular/issues/17349),讨论了这个问题。该帖子中Matsko的Plunker展示了一个应用程序的工作版本,该版本使用自定义RouteReuseStrategy来强制重新加载组件。


你真是太厉害了,谢谢你的帮助。现在我又有动力继续开发我的应用程序了。 - Francisco
嗨@Francisco - 这怎么解决问题 - 你不可能手动添加所有可能的类别的路由(或者也许你可以?) - Drenai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接