angular6路由复用策略

一. 什么是路由复用? 为什么使用路由复用?

路由在执行过程中对组件无状态操作,即路由在离退时组件状态会一并删除,再次进入该页面会重新进入ngOnInit中,大部分情况这样是合理的。

但是在移动端这边,一般都是有查询列表页,用户可以进行下拉触底加载更多数据,这时候,当用户点击某项进入详情页后,再次跳回列表页时,会发现列表页重新刷新了一遍,用户上次的访问滚动记录已经不在了…这时候肯定会被提出需求:记住用户上次滚动的位置,数据在跳页面后不能丢失!

这时候就需要利用angular提供的RouteReuseStrategy路由复用策略,重新构建改组件。

二. RouteReuseStrategy的重要概念
  • shouldDetach 是否允许复用路由

  • store 当路由离开时会触发,存储路由

  • shouldAttach 是否允许还原路由

  • retrieve 获取存储路由

  • shouldReuseRoute 进入路由触发,是否同一路由时复用路由

用一种白话文像是这样:把路由 /list 设置为允许复用(shouldDetach),然后将路由快照存在 store 当中;当 shouldReuseRoute 成立时即:再次遇到 /list 路由后表示需要复用路由,先判断 shouldAttach 是否允许还原,最后从 retrieve 拿到路由快照并构建组件。

三. 举例来创建路由复用策略demo
  1. 新建simple-reuse-strategy.ts,路由复用策略默认对所有路由复用 可通过给路由配置项增加data: { keep: true }来进行选择性使用。
import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';
export class SimpleReuseStrategy implements RouteReuseStrategy {
  public static handlers: { [key: string]: DetachedRouteHandle } = {};
  // 表示对路由允许复用
  public shouldDetach(route: ActivatedRouteSnapshot): boolean {
    // 默认对所有路由不可复用 可通过给路由配置项增加data: { keep: true }来进行选择性使用,代码如下
    // true为可服用路由
    // false为不可复用路由
    return route.data.keep ? true : false;
  }
  // 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象
  public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    AppRoutingCache.handlers[route.routeConfig.path] = handle;
  }
  // 若path在缓存中有的都认为允许还原路由
  public shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!route.routeConfig && !!AppRoutingCache.handlers[route.routeConfig.path];
  }
  // 从缓存中获取快照,若无则返回null
  public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    if (!route.routeConfig) {
      return null;
    }
    return AppRoutingCache.handlers[route.routeConfig.path];
  }
  // 进入路由触发,判断是否同一路由
  public shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === current.routeConfig;
  }
}
  1. 将策略注册到模块当中:
// app.module.ts
import {RouteReuseStrategy, RouterModule, Routes} from '@angular/router';
import {SimpleReuseStrategy} from './simple-reuse-strategy';
providers: [
  /*路由复用策略*/
  { provide: RouteReuseStrategy, useClass: SimpleReuseStrategy }
]
  1. 设置特定路由使用路由复用策略:keep:true
{
    path: 'advanceSearch',
    component: AdvanceSearchComponent,
    canActivate: [BaiduStatisticsGuard],
    data: {
      title: '全国律师诚信信息公示平台',
      keep: true
    }
  },
  1. 使用路由复用策略后,ngOnInit 的方法不会再执行,这个时候需要把 ngOnInit的方法写在NavigationEnd里
import { filter } from 'rxjs/operators';
import { Router, NavigationEnd } from '@angular/router';

  constructor(
    private route: ActivatedRoute,
    private router: Router,
  ) {
    this.route.queryParams.subscribe(param => {
        ...
    });
  }
                                     
// 获取上次页面滚动轴scrollTop距离,重新复位
this.router.events.pipe(
    filter(event => event instanceof NavigationEnd)
).subscribe((event: NavigationEnd) => {
    if (event.url === '/advanceSearch') {
        if (this.resultList) {
            this.resultList.nativeElement.scrollTop = this.router['scrollTop'];
        }
    }
});
参考文档

https://segmentfault.com/a/1190000011430157

https://segmentfault.com/a/1190000014944087

你可能感兴趣的:(angular6系列)