Прекратите перезагружать весь контент при изменении маршрута

javascript angularjs angular typescript angular-routing

1903 просмотра

3 ответа

У меня есть маршрут, подобный следующему:, 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-вызов. Если бы в этом компоненте были другие вещи, этого не произошло бы при смене маршрутов.

Есть идеи, как это решить?

РЕДАКТИРОВАТЬ : Вот Plunkr, показывая ожидаемое поведение. Однако я использовал прежние ROUTER_DIRECTIVES, которые устарели сейчас.

Автор: brians69 Источник Размещён: 08.11.2019 11:21

Ответы (3)


1 плюс

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

На этом плунжере нет видимых миганий , потому что данные жестко запрограммированы, поэтому не нужно ждать ответа сервера.

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

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

Автор: BeetleJuice Размещён: 20.08.2016 03:09

0 плюса

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

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

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

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

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

Автор: Rob Размещён: 20.08.2016 01:56

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 с рабочим примером.

Автор: brians69 Размещён: 22.08.2016 01:58
Вопросы из категории :
32x32