programing

파라미터 변경 시 Angular 2 재로드 경로

linuxpc 2023. 8. 19. 09:55
반응형

파라미터 변경 시 Angular 2 재로드 경로

저는 현재 첫 번째 Angular 2 Application을 작성하고 있습니다.다음과 같은 단순 템플릿이 있는 OverviewComponent가 있습니다.

<div class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>

시 액 스 할 때/라우터가 다음으로 리디렉션합니다./overview그리고 나서 라우터 콘센트 안에 지도를 로드합니다.<app-list>에는 클릭 , 이 목록은 " " " " 를 .<app-detail>앱 구성 요소 대신 표시됩니다. 나는 다음과 합니다./details/:id(내 경로에서).

위의 모든 것이 완전히 정상적으로 작동합니다.목록 항목 중 하나를 클릭하면 세부 정보가 표시되지만 다른 목록 요소를 선택해도 보기가 새 세부 정보로 변경되지 않습니다.URL은 변경되지만 콘텐츠는 다시 로드되지 않습니다.세부 구성 요소를 다시 초기화하려면 어떻게 해야 합니까?

구성 요소 수준에서 routeRuseStrategy를 직접 변경할 수 있습니다.

constructor(private router: Router) {

      // force route reload whenever params change;
      this.router.routeReuseStrategy.shouldReuseRoute = () => false;

}

마찬가지로 재사용 전략도 전 세계적으로 변경될 수 있습니다.

이것이 반드시 당신의 문제를 직접적으로 해결하는 것은 아니지만, 이 질문이 어떻게 "쿼리 매개변수가 변경될 경우 각도 2 다시 로드 URL"에 대한 첫 번째 검색 결과인지를 보면 다음 사람이 github 문제를 파헤치는 것을 막을 수 있습니다.

첫 번째 최종 릴리스에 따라 이 문제가 해결되었습니다.

매개 변수가 변경될 때 구성 요소의 상태를 올바르게 재설정하는 데 많은 주의를 기울입니다.

this.route.params.subscribe(params => {
    this.param = params['yourParam'];
    this.initialiseState(); // reset and set based on new parameter this time
});

여기에 추가해야 할 또 다른 대안은 모듈에 경로 재사용 전략을 제공하는 것입니다.

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

라우터의 기본 동작은 구성이 동일한 경우(이 질문에서 :id 매개 변수만 변경하는 경우) 경로를 다시 사용하는 것입니다.경로를 다시 사용하지 않도록 전략을 변경하면 구성 요소가 다시 로드되므로 구성 요소의 경로 변경에 가입할 필요가 없습니다.

경로 재사용 전략의 구현은 다음과 같습니다.

export class AARouteReuseStrategy extends RouteReuseStrategy {
  shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  store(route: ActivatedRouteSnapshot, handle: {}): void {

  }
  shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return false;
  }
  retrieve(route: ActivatedRouteSnapshot): {} {
     return null;
 }
 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
   return false; // default is true if configuration of current and future route are the same
 }
}

저도 여기에 몇 가지 글을 썼습니다.

https://pjsjava.blogspot.no/2018/01/angular-components-not-reloading-on.html

Angular 7 프로젝트에서 라우터를 가져옵니다.

import { Router } from '@angular/router';

라우터의 개체 만들기

constructor(private router: Router) {

}

routeRuseStrategy를 사용하여 라우터 매개 변수 변경 검색

ngOnInit() {
    this.router.routeReuseStrategy.shouldReuseRoute = () => {
      // do your task for before route

      return false;
    }
}

이 옵션을 사용합니다.constructor()

this.router.routeReuseStrategy.shouldReuseRoute = () => false;

수신된 파라미터의 변경을 감지할 수 있습니다. 이 경우 Resolve를 사용하여 정보를 로드하므로 파라미터가 필요하지 않습니다(변경된 경우에만 감지).이것이 저의 최종 해결책입니다.

public product: Product;
private parametersObservable: any;

constructor(private route: ActivatedRoute) {
}

ngOnInit() {
  this.parametersObservable = this.route.params.subscribe(params => {
    //"product" is obtained from 'ProductResolver'
    this.product = this.route.snapshot.data['product'];
  });
}

//Don't forget to unsubscribe from the Observable
ngOnDestroy() {
  if(this.parametersObservable != null) {
    this.parametersObservable.unsubscribe();
  }
}

제가 바로 여기서 제안할 문제와 유사한 문제에 대한 답이 있는지 알 수 없으므로, 어쨌든 그렇게 하겠습니다.

저는 다음과 같은 방법으로 '가짜' 다시 로드를 할 수 있었습니다.

기본적으로 사용할 '실제' 구성요소로 리디렉션하는 구성요소를 만드는 것이었습니다.

@Component({
  selector: 'camps-fake',
  template: ''
})
export class FakeComponent implements OnInit {

  constructor(private _router:Router,
              private _route:ActivatedRoute)
  { }

  ngOnInit() {
    let id:number = -1;
    this._route.params.forEach((params:Params) => {
      id = +params['id'];
    });

    let link:any[] = ['/details', id];
    this._router.navigate(link);
  }

}

목록 는 " 서라라가탐목항록선다택니합목을색따할우터다▁to니▁so▁the"로 합니다./fake/:idURL에서 ID를 추출하고 '실제' 구성 요소로 이동합니다.

더 쉽고, 더 화려한 방법이 있을 수 있다는 것을 알지만, 가짜가 관심을 끌지 못하기 때문에 이 해결책이 꽤 잘 작동한다고 생각합니다.페이지를 다시 로드할 때의 '플래시'는 부정적인 측면이지만 내 CSS 지식이 도달하는 한 그것을 다루기 위한 전환이 있을 수 있습니다.

this.route.paramMap.subscribe(params => {
  //fetch your new parameters here, on which you are switching the routes and call ngOnInit()
  this.ngOnInit();
 });

paramMap 내부에서 ngOnInit()를 호출하기만 하면 새로 로드된 데이터로 전체 페이지를 초기화합니다.

이것이 도움이 되기를 바랍니다.

constructor(private router: Router){
 // override the route reuse strategy

 this.router.routeReuseStrategy.shouldReuseRoute = function(){
    return false;
 }

 this.router.events.subscribe((evt) => {
    if (evt instanceof NavigationEnd) {
       // trick the Router into believing it's last link wasn't previously loaded
       this.router.navigated = false;
       // if you need to scroll back to top, here is the right place
       window.scrollTo(0, 0);
    }
});

}

저는 이것들 중 어느 것도 Angular 8에 대한 좋고 철저한 해결책이 아니라는 것을 몰랐습니다.일부 제안은 무한 루프를 생성하여 스택 오버플로를 초래했습니다.다른 것들은 내 입맛에 너무 까다롭습니다.온라인에서 좋은 해결책을 찾았지만 여기에 링크만 올릴 수는 없기 때문에 링크를 기반으로 제가 무엇을 했는지, 왜 그것이 확실한 해결책이라고 생각하는지 최선을 다해 정리하겠습니다.이를 통해 다른 경로가 아닌 동작이 필요한 특정 경로에만 영향을 줄 수 있으며 사용자 지정 클래스를 롤할 필요가 없습니다.

https://medium.com/engineering-on-the-incline/reloading-current-route-on-click-angular-5-1a1bfc740ab2 있는 Simon McClive의 솔루션에서.

먼저 앱 라우팅 모듈 구성을 수정합니다.

@ngModule({ imports: [RouterModule.forRoot(routes, {onSameUrlNavigation: ‘reload’})],
exports: [RouterModule] })

그런 다음 영향을 줄 경로를 수정합니다.인증을 사용하지 않는 경우 canActivate 매개 변수를 생략할 수 있습니다.

export const routes: Routes = [
 {
   path: ‘invites’,
   component: InviteComponent,
   children: [
     {
       path: ‘’,
       loadChildren: ‘./pages/invites/invites.module#InvitesModule’,
     },
   ],
   canActivate: [AuthenticationGuard],
   runGuardsAndResolvers: ‘always’, //there are three options for this - see Simon's post. 'Always' is the heaviest-handed and maybe more than you need.
 }
]

마지막으로, 탐색 이벤트를 청취하도록 클래스를 업데이트하고 그에 따라 행동합니다( 나가는 길에 청취자 등록을 취소해야 함).

export class AwesomeComponent implements OnInit, OnDestroy{

 // ... your class variables here
 navigationSubscription;

 constructor( private router: Router ) {

   // subscribe to the router events and store the subscription so
   // we can unsubscribe later

   this.navigationSubscription = this.router.events.subscribe((e: any) => {
     // If it is a NavigationEnd event, re-initalize the component
     if (e instanceof NavigationEnd) {
       this.myInitFn();
     }
   });
 }

 myInitFn() {
   // Reset anything affected by a change in route params
   // Fetch data, call services, etc.
 }

 ngOnDestroy() {
    // avoid memory leaks here by cleaning up
    if (this.navigationSubscription) {  
       this.navigationSubscription.unsubscribe();
    }
  }
}

이벤트를 사용하여 해결했습니다. 하위 구성 요소가 새 링크를 보내고 이벤트를 보내면 부모가 변경 사항을 찾아 필요한 데이터를 다시 로드하는 어떤 다시 로드 기능을 호출할 수 있습니다.또 다른 옵션은 경로 매개 변수를 구독하고 변경할 때 발견했지만 angular2의 남자들은 router.navigate 함수에 매개 변수를 추가하는 것을 고려해야 한다고 생각합니다. 이는 강제로 다시 로드할 수 있습니다.(forceReload=true)

관용적인 접근법은 관찰 가능한 것과| asyc템플릿의 파이프를 선택합니다.

(https://medium.com/ @httpiaapsynkova/component-2-component-component-component-capsynka-9f3dfab23f5에서 다운로드 - 자세한 내용은 더 읽기)

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/pluck';

@Component({
  selector: 'app-detail-reusable',
  template: `<p>detail reusable for {{id$| async}} param </p>`
})
export class DetailReusableComponent implements OnInit {
  id$: Observable<string>;

  constructor(private route: ActivatedRoute) {
  }

  ngOnInit() {
    this.id$ = this.route.params.pluck('id');
  }
}

REST API에서 추가 세부 정보를 가져오는 경우 다음을 사용할 수 있습니다.switchMap예:

import {Component, OnInit} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/pluck';

@Component({
  selector: 'app-detail-reusable',
  template: `<ul><li *ngFor="let item of items$ | async">{{ item.name }}</li></ul>`
})
export class DetailReusableComponent implements OnInit {
  items$: Observable<string[]>;

  constructor(private route: ActivatedRoute) {
  }

  ngOnInit() {
    this.items$ = this.route.params.pipe(
      pluck("id"),
      switchMap(id => this.http.get<string[]>(`api/items/${id}`))  // or whatever the actual object type is
    );
  }
}

| async파이프는 자동으로 구독하고 다음은id$또는items$관찰 가능은 경로 매개 변수가 변경되면 업데이트되어 API 데이터 가져오기를 트리거합니다(에서).items$보기를 업데이트합니다.

현재 직접 지원되지 않습니다.https://github.com/angular/angular/issues/9811 도 참조하십시오.

당신이 할 수 있는 것은 다음과 같습니다.

<div *ngIf="doShow" class="row">
  <div class="col-lg-8">
    <router-outlet></router-outlet>
  </div>
  <div class="col-lg-4">
    <app-list></app-list>
  </div>
</div>
doShow:boolean: true;

constructor(private _activatedRoute: ActivatedRoute, private _router:Router, private cdRef:ChangeDetectorRef) {
  _router.routerState.queryParams.subscribe(
    data => {
      console.log('queryParams', data['st']); 
      this.doShow = false;
      this.cdRef.detectChanges();
      this.doShow = true;
  });
}

(테스트되지 않음)

시공자에게 이것을 적용하는 것이 가장 좋은 해결책이었습니다.

this.router.routeReuseStrategy.shouldReuseRoute = () => false;

그러나 전체 앱에 대한 재사용 전략의 동작을 업데이트함에 따라! 저는 바퀴를 재창조할 필요 없이 이 문제를 완전히 해결하기 위해 몇 가지 다른 접근법을 시도했습니다.

결론은 구성 요소를 파괴할 때 값을 true로 설정하면 됩니다.

ngOnDestroy() {
    this.router.routeReuseStrategy.shouldReuseRoute = () => true;
}

언급URL : https://stackoverflow.com/questions/38971660/angular-2-reload-route-on-param-change

반응형