管理系統 tab 切換頁,是一種常見的需求,大概以下:php
點擊左邊菜單,右邊顯示相應的選項卡,而後不一樣的選項卡面能夠同時編輯,切換時信息不掉失!css
用php或.net,java的開發技術,大概是切換顯示,而後加一個ifram來作到,或者經過ajax加載信息顯示相應的層.html
可是若是用angular 要如何實現呢?第一個想法,是否能夠用一樣的ifarm來實現呢?java
第二個想到的是路由插座大概是這樣的ajax
<router-outlet name="main-content" (activate)="activate($event)" (deactivate)='onDeactivate($event)' ></router-outlet> bootstrap
但都沒能實現,因而在想一個簡單的tab頁面就這麼難嗎?緩存
或者真的沒有什麼簡單的方法了嗎?app
很長一段時間,沒有去管這個了ide
由於我知道本身對angular的理解和學習還不夠,因而就放下了很長一段時間,直到在知乎看到一篇文章學習
因而有了一種思路,花了半天的時間終於實現了anguar 4 tab 切換頁大概思路實現以下:
1、實現 RouteReuseStrategy 接口自定義一個路由利用策略
SimpleReuseStrategy.ts代碼以下:
1 import { RouteReuseStrategy, DefaultUrlSerializer, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; 2 3 export class SimpleReuseStrategy implements RouteReuseStrategy { 4 5 public static handlers: { [key: string]: DetachedRouteHandle } = {} 6 7 /** 表示對全部路由容許複用 若是你有路由不想利用能夠在這加一些業務邏輯判斷 */ 8 public shouldDetach(route: ActivatedRouteSnapshot): boolean { 9 return true; 10 } 11 12 /** 當路由離開時會觸發。按path做爲key存儲路由快照&組件當前實例對象 */ 13 public store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { 14 SimpleReuseStrategy.handlers[route.routeConfig.path] = handle 15 } 16 17 /** 若 path 在緩存中有的都認爲容許還原路由 */ 18 public shouldAttach(route: ActivatedRouteSnapshot): boolean { 19 return !!route.routeConfig && !!SimpleReuseStrategy.handlers[route.routeConfig.path] 20 } 21 22 /** 從緩存中獲取快照,若無則返回nul */ 23 public retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { 24 if (!route.routeConfig) { 25 return null 26 } 27 28 return SimpleReuseStrategy.handlers[route.routeConfig.path] 29 } 30 31 /** 進入路由觸發,判斷是否同一路由 */ 32 public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { 33 return future.routeConfig === curr.routeConfig 34 } 35 }
2、策略註冊到模塊當中:
1 import { BrowserModule } from '@angular/platform-browser'; 2 import { NgModule } from '@angular/core'; 3 import { FormsModule } from '@angular/forms'; 4 import { CommonModule as SystemCommonModule } from '@angular/common'; 5 import { AppComponent } from './app.component'; 6 import { AppRoutingModule,ComponentList } from './app.routing' 7 import { SimpleReuseStrategy } from './SimpleReuseStrategy'; 8 import { RouteReuseStrategy } from '@angular/router'; 9 10 @NgModule({ 11 declarations: [ 12 AppComponent, 13 ComponentList 14 ], 15 imports: [ 16 BrowserModule, 17 AppRoutingModule, 18 FormsModule, 19 SystemCommonModule 20 ], 21 providers: [ 22 { provide: RouteReuseStrategy, useClass: SimpleReuseStrategy } 23 ], 24 bootstrap: [AppComponent] 25 }) 26 export class AppModule { }
上面兩步基本上實現了複用策略但要實現第一張效果圖,仍是要作一些其它工做
3、定義路由添加一些data數據路由代碼以下:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AboutComponent } from './home/about.component' import { HomeComponent } from './home/home.component' import { NewsComponent } from './home/news.component' import { ContactComponent } from './home/contact.component' export const routes: Routes = [ { path: '', redirectTo: 'home', pathMatch: 'full', }, { path: 'home', component: HomeComponent,data: { title: '首頁', module: 'home', power: "SHOW" } }, { path: 'news',component: NewsComponent ,data: { title: '新聞管理', module: 'news', power: "SHOW" }}, { path: 'contact',component: ContactComponent ,data: { title: '聯繫咱們', module: 'contact', power: "SHOW" }}, { path: 'about', component: AboutComponent,data: { title: '關於咱們', module: 'about', power: "SHOW" } }, ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { } export const ComponentList=[ HomeComponent, NewsComponent, AboutComponent, ContactComponent ]
4、在<router-outlet></router-outlet> component 實現路由事件 events,app.component代碼以下:
1 import { Component } from '@angular/core'; 2 import { SimpleReuseStrategy } from './SimpleReuseStrategy'; 3 import { ActivatedRoute, Router, NavigationEnd } from '@angular/router'; 4 import { Title } from '@angular/platform-browser'; 5 import 'rxjs/add/operator/filter'; 6 import 'rxjs/add/operator/map'; 7 import 'rxjs/add/operator/mergeMap'; 8 9 @Component({ 10 selector: 'app-root', 11 styleUrls:['app.css'], 12 templateUrl: 'app.html', 13 providers: [SimpleReuseStrategy] 14 }) 15 16 export class AppComponent { 17 18 //路由列表 19 menuList: Array<{ title: string, module: string, power: string,isSelect:boolean }>=[]; 20 21 constructor(private router: Router, 22 private activatedRoute: ActivatedRoute, 23 private titleService: Title) { 24 25 //路由事件 26 this.router.events.filter(event => event instanceof NavigationEnd) 27 .map(() => this.activatedRoute) 28 .map(route => { 29 while (route.firstChild) route = route.firstChild; 30 return route; 31 }) 32 .filter(route => route.outlet === 'primary') 33 .mergeMap(route => route.data) 34 .subscribe((event) => { 35 //路由data的標題 36 let title = event['title']; 37 this.menuList.forEach(p => p.isSelect=false); 38 var menu = { title: title, module: event["module"], power: event["power"], isSelect:true}; 39 this.titleService.setTitle(title); 40 let exitMenu=this.menuList.find(info=>info.title==title); 41 if(exitMenu){//若是存在不添加,當前表示選中 42 this.menuList.forEach(p => p.isSelect=p.title==title); 43 return ; 44 } 45 this.menuList.push(menu); 46 }); 47 } 48 49 //關閉選項標籤 50 closeUrl(module:string,isSelect:boolean){ 51 //當前關閉的是第幾個路由 52 let index=this.menuList.findIndex(p=>p.module==module); 53 //若是隻有一個不能夠關閉 54 if(this.menuList.length==1) return ; 55 56 this.menuList=this.menuList.filter(p=>p.module!=module); 57 //刪除複用 58 delete SimpleReuseStrategy.handlers[module]; 59 if(!isSelect) return; 60 //顯示上一個選中 61 let menu=this.menuList[index-1]; 62 if(!menu) {//若是上一個沒有下一個選中 63 menu=this.menuList[index+1]; 64 } 65 // console.log(menu); 66 // console.log(this.menuList); 67 this.menuList.forEach(p => p.isSelect=p.module==menu.module ); 68 //顯示當前路由信息 69 this.router.navigate(['/'+menu.module]); 70 } 71 }
app.html 的代碼以下:
1 <div class="row"> 2 <div class="col-md-4"> 3 <ul> 4 <li><a routerLinkActive="active" routerLink="/home">首頁</a></li> 5 <li><a routerLinkActive="active" routerLink="/about">關於咱們</a></li> 6 <li><a routerLinkActive="active" routerLink="/news">新聞中心</a></li> 7 <li><a routerLinkActive="active" routerLink="/contact">聯繫咱們</a></li> 8 </ul> 9 </div> 10 <div class="col-md-8"> 11 <div class="crumbs clearfix"> 12 <ul> 13 <ng-container *ngFor="let menu of menuList"> 14 <ng-container *ngIf="menu.isSelect"> 15 <li class="isSelect"> 16 <a routerLink="/{{ menu.module }}">{{ menu.title }}</a> 17 <span (click)="closeUrl(menu.module,menu.isSelect)">X</span> 18 </li> 19 </ng-container> 20 <ng-container *ngIf="!menu.isSelect"> 21 <li> 22 <a routerLink="/{{ menu.module }}">{{ menu.title }}</a> 23 <span (click)="closeUrl(menu.module,menu.isSelect)">X</span> 24 </li> 25 </ng-container> 26 </ng-container> 27 </ul> 28 </div> 29 <router-outlet></router-outlet> 30 </div> 31 </div>
總體效果以下:
最終點擊菜單顯示相應的標籤選中,能夠切換編輯內容,關閉標籤時,從新點擊菜單能夠從新加載內容。
源代碼:好吧,我不知道怎樣上傳源代碼:)!