2016-08-20 3 views
1

У меня есть маршрут следующим образом: page/:id, где он загружает различное содержимое для каждого id. Однако каждый раз, когда я перехожу на другую страницу, он перезагружает весь контент. Я хотел бы перезагрузить только данные, поступающие из API.Остановить перезагрузку всего содержимого при изменении маршрута

Навигация:

<ul> 
<li [routerLink]="['/page', 1]">Page 1</li> 
<li [routerLink]="['/page', 2]">Page 2</li> 
<li [routerLink]="['/page', 3]">Page 3</li> 
</ul> 

Шаблон: <h1 *ngIf="data">{{data.name}}</h1>

Компонент:

export class DataComponent implements OnInit { 

    data: any; 
    error: any; 

    constructor(
    private route: ActivatedRoute, 
    private service: DataService 
) {} 

    ngOnInit() { 
    this.getData(); 
    } 

    getData() { 
    this.service.getData() 
     .subscribe(
     res => this.data = res, 
     error => this.error = error 
    ); 
    } 

} 

Если вы идете к этому Plunker, вы увидите черный прямоугольник мигает каждый раз, когда изменяется маршрут , В идеальном случае черная часть осталась бы неповрежденной, только внутренние данные изменились бы.

Я также заметил, что это мерцающее поведение происходит, только если я использую HTTP-вызов. Если бы у меня были другие вещи в этом компоненте, это не произошло бы при смене маршрутов.

Любые идеи о том, как это решить?

EDIT: Here's a Plunkr, показывающий ожидаемое поведение. Тем не менее, я использовал бывшие ROUTER_DIRECTIVES, которые теперь устарели.

ответ

0

Расширение @ Ответ Роба, мне удалось решить эту проблему с помощью защитника Resolve.Тем не менее, я делал несколько ошибок в его реализации.

Я создал новый data-resolve, где я решить HTTP вызов перед инициализацией маршрут:

@Injectable() 
export class DataResolve implements Resolve { 

    constructor(private service: DataService, private router: Router) {} 

    resolve(route: ActivatedRouteSnapshot): 
    Observable<any> | Promise<any> | any { 
     return this.service.getData().then(data => { 
     if (data) { 
      return data; 
     } else { 
      this.router.navigate(['/page/1']); 
     return false; 
     } 
    }); 
    } 
} 

Затем мне нужно добавить, что сервис-провайдеров моего модуля:

providers: [DataService, DataResolve]

А также указать маршрутизацию, чтобы решить, что до загрузки маршрута:

resolve: { pages: DataResolve }

После этого, я буду иметь массив я могу использовать в моем компоненте, чтобы получить данные:

this.route.data.forEach((data: {pages}) => { 
    this.data = data.pages; 
}); 

Я также обновил свой Plunker с рабочим примером.

0

Вы уже загружаете только контент из API. Черный ящик мерцает, потому что вы моделируете h1, а h1 меняется. Если вам нужна коробка для каждой страницы, переместите ее до шаблона AppComponent.

<div class="box"> 
    <router-outlet></router-outlet> 
</div> 

Затем переместите стили к селектору .box, а не h1.

Другая проблема заключается в том, что высота окна будет разрушаться и расширяться, пока содержимое будет удалено и обновлено. Вы можете исправить это, воспользовавшись защитой вашего маршрута.

https://angular.io/docs/ts/latest/guide/router.html#!#resolve-guard

+0

Я вижу. Однако, интересно, нет ли другого пути. Если у меня будет более сложная структура, у меня будет такая же проблема: черный ящик останется, но другая статическая информация внутри него все равно будет мерцать. Я также заметил, что это происходит, только если я использую HTTP-вызов. Если бы у меня были другие вещи в этом компоненте, он не мерцал при смене маршрутов. – brians69

+0

Он не должен мерцать, если вы используете защиту разрешения, потому что маршрут не загружается до тех пор, пока HTTP-запрос не будет разрешен с сервера. – Rob

+0

Может быть, я что-то делаю неправильно? Я обновил свой плункер: http://plnkr.co/edit/8l2GwRzhcVKF4xUea55o?p=preview – brians69

1

Ваше моргание происходит потому, что при навигации, DataComponent разрушен и заново построен, но он не может быть показано, пока новые данные не поступает с сервера, потому что вы блокируете его дисплей с *ngIf="data". On this plunker, я добавил 1 секунду задержки ответа сервера, чтобы сделать проблему очевидной. Обратите внимание, что мигает только DataComponent. Остальная часть PagesComponent нет.

On this plunker, нет видимых мерцаний, потому что данные жестко закодированы, поэтому нет ожиданий ответа сервера.

Чтобы облегчить мигание, не используйте *ngIf, так как это полностью удаляет элемент из дома. On this plunker, мигание не происходит даже в ожидании получения данных с сервера.

В принципе, до тех пор, пока вы решите скрыть элемент до тех пор, пока данные не прибудут, всякий раз, когда компонент будет повторно инициализирован, вы увидите мерцание.

+0

Спасибо за объяснение. На самом деле мой вопрос остается. Предположим, что данные не меняются (несмотря на изменение маршрута, свойство «имя» одинаково). Он должен хранить одни и те же данные (без мигания). Я помню, что у меня было что-то подобное при использовании RC.4 и 'ROUTER_DIRECTIVES', но, по-видимому, поведение было изменено на RC.5. Я постараюсь позже выложить Plunkr. – brians69

+0

Вот Plunker с поведением, которое я ожидаю: http://plnkr.co/edit/ZITXyhXAmWWk2hor13ea?p=preview - Я использую RC.5, но 'ROUTER_DIRECTIVES' вместо' RouterModule'. Интересно, возможно ли иметь такое же поведение, что и «ROUTER_DIRECTIVES» теперь не рекомендуется. – brians69

+0

@drbishop Ваш исходный код подлежит Угловой ошибке. Предполагается, что маршрутизатор повторно использует один и тот же экземпляр компонента при навигации к одному и тому же компоненту (даже если параметры меняются). Однако, по сравнению с «Угловым rc 5», этот механизм не работает на ленивых компонентах, поэтому ваш «PagesComponent» уничтожается и воссоздается, даже если данные не изменяются. См. Https://github.com/angular/angular/issues/10987 – BeetleJuice

Смежные вопросы