Angular 2+ 中,懶加載 + 輔助路由 + 路由策略 三者結(jié)合時(shí)的報(bào)錯(cuò)賞析

Angular 2+ 中輔助路由的應(yīng)用之前也已經(jīng)寫過了,大概如下:
代碼中:

<a [routerLink]="[{outlets:{primary:'components/buttons',aux:'pages/login'}}]">測試1</a>

地址欄中:

http://localhost:4200/#/components/buttons(aux:pages/404)

路由設(shè)置:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

// Import Containers
import {
FullLayoutComponent,
SimpleLayoutComponent
} from './containers';

export const routes: Routes = [
{
    path: 'components',
    loadChildren: './views/components/components.module#ComponentsModule'
},
{
    path: 'editors',
    loadChildren: './views/editors/editors.module#EditorsModule'
},
{
    path: 'pages',
    component: SimpleLayoutComponent,
    outlet: 'aux',
    data: {
    title: 'Pages'
    },
    children: [
    {
        path: '',
        loadChildren: './views/pages/pages.module#PagesModule',
    }
    ]
}
];

@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}

界面:
In app.component.html

<app-header></app-header>
<div class="app-body">
  <app-sidebar></app-sidebar>
  <!-- Main content -->
  <main class="main">
    <!-- Breadcrumb -->
    <ol class="breadcrumb">
      <app-breadcrumbs></app-breadcrumbs>
    </ol>
    <div class="container-fluid">
      <router-outlet></router-outlet>
    </div><!-- /.conainer-fluid -->
  </main>
  <app-aside></app-aside>
</div>
<app-footer></app-footer>

In app-aside.component.html

<aside class="aside-menu">
  <router-outlet name="aux"></router-outlet>
</aside>

In simple-layout.component.ts

import { Component } from '@angular/core';
@Component({
  template: '<router-outlet></router-outlet>',
})
export class SimpleLayoutComponent { }

In editors-routing.module.ts

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
  {
    path: '',
    data: {
      title: 'Editors'
    },
    children: [
      {
        path: 'text-editors',
        loadChildren: './text-editors/text-editors.module#TextEditorsModule'
      },
      {
        path: 'code-editors',
        loadChildren: './code-editors/code-editors.module#CodeEditorsModule'
      }
    ]
  }
];
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class EditorsRoutingModule {}

之前的路由策略:

export class CustomReuseStrategy implements RouteReuseStrategy {
    handlers: {[key: string]: DetachedRouteHandle} = {};
    shouldDetach(route: ActivatedRouteSnapshot): boolean {
        console.debug('CustomReuseStrategy:shouldDetach', route);
        return true;
    }
    store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
        console.debug('CustomReuseStrategy:store', route, handle);
        this.handlers[route.routeConfig.path] = handle;
    }
    shouldAttach(route: ActivatedRouteSnapshot): boolean {
        console.debug('CustomReuseStrategy:shouldAttach', route);
        return !!route.routeConfig && !!this.handlers[route.routeConfig.path];
    }
    retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
        console.debug('CustomReuseStrategy:retrieve', route);
        return this.handlers[route.routeConfig.path];//從暫存處取回
    }
    shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
        //在此處可以取得跳轉(zhuǎn)前和跳轉(zhuǎn)后的路由路徑
        console.debug('CustomReuseStrategy:shouldReuseRoute', future, curr);
        return future.routeConfig === curr.routeConfig;
    }
}

加上路由策略以后就會(huì)使得帶輔助路由的跳轉(zhuǎn)報(bào)錯(cuò):

Cannot reattach ActivatedRouteSnapshot created from a different route

這個(gè)問題之前在 AngularGit 上的那個(gè) issueCannot reattach ActivatedRouteSnapshot created from a different route 存在了一年多,并沒有解決,包括查閱了網(wǎng)上的各種偏方,也并不好使,后來好不容易百度到這樣的解決方案:

后來的路由策略:

import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';

export class SimpleReuseStrategy implements RouteReuseStrategy {
  public static handlers: { [key: string]: DetachedRouteHandle } = {};
  /** 表示對所有路由允許復(fù)用 如果你有路由不想利用可以在這加一些業(yè)務(wù)邏輯判斷 */
  public shouldDetach(route: ActivatedRouteSnapshot): boolean {
    return true;
  }
  /** 當(dāng)路由離開時(shí)會(huì)觸發(fā)。按path作為key存儲(chǔ)路由快照&組件當(dāng)前實(shí)例對象 */
  public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
    SimpleReuseStrategy.handlers[route.routeConfig.path] = handle
  }
  /** 若 path 在緩存中有的都認(rèn)為允許還原路由 */
  public shouldAttach(route: ActivatedRouteSnapshot): boolean {
    return !!route.routeConfig && !!SimpleReuseStrategy.handlers[route.routeConfig.path]
  }
  /** 從緩存中獲取快照,若無則返回nul */
  public retrieve_bak(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    if (!route.routeConfig) {
      return null
    }
    return SimpleReuseStrategy.handlers[route.routeConfig.path]
  }
  public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
    if (!route.routeConfig) {
      return null;
    }
    if (route.routeConfig.loadChildren) {
      return null;
    }
    return SimpleReuseStrategy.handlers[route.routeConfig.path];
  }
  /** 進(jìn)入路由觸發(fā),判斷是否同一路由 */
  public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
    return future.routeConfig === curr.routeConfig
  }
}

實(shí)踐證明這個(gè)并不會(huì)報(bào)錯(cuò),是可以用的,Payload 就是這個(gè)函數(shù):

retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle {
  if (!route.routeConfig) return null;
  if(route.routeConfig.loadChildren) return null;
  return this.handlers[route.routeConfig.path];
}

總之 Angular 的路由是極其重要的組件,也是存在問題比較多的組件。

參考資料:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容