angular4實(shí)現(xiàn)tab欄切換的方法示例
管理系統(tǒng) tab 切換頁,是一種常見的需求,大概如下:

點(diǎn)擊左邊菜單,右邊顯示相應(yīng)的選項(xiàng)卡,然后不同的選項(xiàng)卡面可以同時(shí)編輯,切換時(shí)信息不掉失!
用php或.net,java的開發(fā)技術(shù),大概是切換顯示,然后加一個(gè)ifram來做到,或者通過ajax加載信息顯示相應(yīng)的層.
但是如果用angular 要如何實(shí)現(xiàn)呢?第一個(gè)想法,是否可以用同樣的ifarm來實(shí)現(xiàn)呢?
第二個(gè)想到的是路由插座大概是這樣的
<router-outlet name="main-content" (activate)="activate($event)" (deactivate)='onDeactivate($event)' ></router-outlet>
但都沒能實(shí)現(xiàn),于是在想一個(gè)簡單的tab頁面就這么難嗎?
或者真的沒有什么簡單的方法了嗎?
很長一段時(shí)間,沒有去管這個(gè)了
因?yàn)槲抑雷约簩ngular的理解和學(xué)習(xí)還不夠,于是就放下了很長一段時(shí)間,直到在知乎看到一篇文章
于是有了一種思路,花了半天的時(shí)間終于實(shí)現(xiàn)了anguar 4 tab 切換頁大概思路實(shí)現(xiàn)如下:
一、實(shí)現(xiàn) RouteReuseStrategy 接口自定義一個(gè)路由利用策略
SimpleReuseStrategy.ts代碼如下:
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í)會觸發(fā)。按path作為key存儲路由快照&組件當(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(route: ActivatedRouteSnapshot): DetachedRouteHandle {
if (!route.routeConfig) {
return null
}
return SimpleReuseStrategy.handlers[route.routeConfig.path]
}
/** 進(jìn)入路由觸發(fā),判斷是否同一路由 */
public shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig
}
}
二、策略注冊到模塊當(dāng)中:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule as SystemCommonModule } from '@angular/common';
import { AppComponent } from './app.component';
import { AppRoutingModule,ComponentList } from './app.routing'
import { SimpleReuseStrategy } from './SimpleReuseStrategy';
import { RouteReuseStrategy } from '@angular/router';
@NgModule({
declarations: [
AppComponent,
ComponentList
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
SystemCommonModule
],
providers: [
{ provide: RouteReuseStrategy, useClass: SimpleReuseStrategy }
],
bootstrap: [AppComponent]
})
export class AppModule { }
上面兩步基本上實(shí)現(xiàn)了復(fù)用策略但要實(shí)現(xiàn)第一張效果圖,還是要做一些其它工作
三、定義路由添加一些data數(shù)據(jù)路由代碼如下:
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: '聯(lián)系我們', module: 'contact', power: "SHOW" }},
{ path: 'about', component: AboutComponent,data: { title: '關(guān)于我們', module: 'about', power: "SHOW" } },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
export const ComponentList=[
HomeComponent,
NewsComponent,
AboutComponent,
ContactComponent
]
四、在<router-outlet></router-outlet> component 實(shí)現(xiàn)路由事件 events,app.component代碼如下:
import { Component } from '@angular/core';
import { SimpleReuseStrategy } from './SimpleReuseStrategy';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import { Title } from '@angular/platform-browser';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
@Component({
selector: 'app-root',
styleUrls:['app.css'],
templateUrl: 'app.html',
providers: [SimpleReuseStrategy]
})
export class AppComponent {
//路由列表
menuList: Array<{ title: string, module: string, power: string,isSelect:boolean }>=[];
constructor(private router: Router,
private activatedRoute: ActivatedRoute,
private titleService: Title) {
//路由事件
this.router.events.filter(event => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map(route => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter(route => route.outlet === 'primary')
.mergeMap(route => route.data)
.subscribe((event) => {
//路由data的標(biāo)題
let title = event['title'];
this.menuList.forEach(p => p.isSelect=false);
var menu = { title: title, module: event["module"], power: event["power"], isSelect:true};
this.titleService.setTitle(title);
let exitMenu=this.menuList.find(info=>info.title==title);
if(exitMenu){//如果存在不添加,當(dāng)前表示選中
this.menuList.forEach(p => p.isSelect=p.title==title);
return ;
}
this.menuList.push(menu);
});
}
//關(guān)閉選項(xiàng)標(biāo)簽
closeUrl(module:string,isSelect:boolean){
//當(dāng)前關(guān)閉的是第幾個(gè)路由
let index=this.menuList.findIndex(p=>p.module==module);
//如果只有一個(gè)不可以關(guān)閉
if(this.menuList.length==1) return ;
this.menuList=this.menuList.filter(p=>p.module!=module);
//刪除復(fù)用
delete SimpleReuseStrategy.handlers[module];
if(!isSelect) return;
//顯示上一個(gè)選中
let menu=this.menuList[index-1];
if(!menu) {//如果上一個(gè)沒有下一個(gè)選中
menu=this.menuList[index+1];
}
// console.log(menu);
// console.log(this.menuList);
this.menuList.forEach(p => p.isSelect=p.module==menu.module );
//顯示當(dāng)前路由信息
this.router.navigate(['/'+menu.module]);
}
}
import { Component } from '@angular/core';
import { SimpleReuseStrategy } from './SimpleReuseStrategy';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
import { Title } from '@angular/platform-browser';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
@Component({
selector: 'app-root',
styleUrls:['app.css'],
templateUrl: 'app.html',
providers: [SimpleReuseStrategy]
})
export class AppComponent {
//路由列表
menuList: Array<{ title: string, module: string, power: string,isSelect:boolean }>=[];
constructor(private router: Router,
private activatedRoute: ActivatedRoute,
private titleService: Title) {
//路由事件
this.router.events.filter(event => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map(route => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter(route => route.outlet === 'primary')
.mergeMap(route => route.data)
.subscribe((event) => {
//路由data的標(biāo)題
let title = event['title'];
this.menuList.forEach(p => p.isSelect=false);
var menu = { title: title, module: event["module"], power: event["power"], isSelect:true};
this.titleService.setTitle(title);
let exitMenu=this.menuList.find(info=>info.title==title);
if(exitMenu){//如果存在不添加,當(dāng)前表示選中
this.menuList.forEach(p => p.isSelect=p.title==title);
return ;
}
this.menuList.push(menu);
});
}
//關(guān)閉選項(xiàng)標(biāo)簽
closeUrl(module:string,isSelect:boolean){
//當(dāng)前關(guān)閉的是第幾個(gè)路由
let index=this.menuList.findIndex(p=>p.module==module);
//如果只有一個(gè)不可以關(guān)閉
if(this.menuList.length==1) return ;
this.menuList=this.menuList.filter(p=>p.module!=module);
//刪除復(fù)用
delete SimpleReuseStrategy.handlers[module];
if(!isSelect) return;
//顯示上一個(gè)選中
let menu=this.menuList[index-1];
if(!menu) {//如果上一個(gè)沒有下一個(gè)選中
menu=this.menuList[index+1];
}
// console.log(menu);
// console.log(this.menuList);
this.menuList.forEach(p => p.isSelect=p.module==menu.module );
//顯示當(dāng)前路由信息
this.router.navigate(['/'+menu.module]);
}
}
app.html 的代碼如下:
<div class="row">
<div class="col-md-4">
<ul>
<li><a routerLinkActive="active" routerLink="/home">首頁</a></li>
<li><a routerLinkActive="active" routerLink="/about">關(guān)于我們</a></li>
<li><a routerLinkActive="active" routerLink="/news">新聞中心</a></li>
<li><a routerLinkActive="active" routerLink="/contact">聯(lián)系我們</a></li>
</ul>
</div>
<div class="col-md-8">
<div class="crumbs clearfix">
<ul>
<ng-container *ngFor="let menu of menuList">
<ng-container *ngIf="menu.isSelect">
<li class="isSelect">
<a routerLink="/{{ menu.module }}">{{ menu.title }}</a>
<span (click)="closeUrl(menu.module,menu.isSelect)">X</span>
</li>
</ng-container>
<ng-container *ngIf="!menu.isSelect">
<li>
<a routerLink="/{{ menu.module }}">{{ menu.title }}</a>
<span (click)="closeUrl(menu.module,menu.isSelect)">X</span>
</li>
</ng-container>
</ng-container>
</ul>
</div>
<router-outlet></router-outlet>
</div>
</div>
整體效果如下:

最終點(diǎn)擊菜單顯示相應(yīng)的標(biāo)簽選中,可以切換編輯內(nèi)容,關(guān)閉標(biāo)簽時(shí),重新點(diǎn)擊菜單可以重新加載內(nèi)容。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
淺談AngularJs 雙向綁定原理(數(shù)據(jù)綁定機(jī)制)
本篇文章主要介紹了淺談AngularJs 雙向綁定原理(數(shù)據(jù)綁定機(jī)制),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-12-12
利用Jasmine對Angular進(jìn)行單元測試的方法詳解
單元測試是一種能夠幫助開發(fā)者驗(yàn)證代碼中某一部分有效性的技術(shù)。下面這篇文章主要給大家介紹了關(guān)于利用Jasmine對Angular進(jìn)行單元測試的相關(guān)資料,文中介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。2017-06-06
AngularJS自定義插件實(shí)現(xiàn)網(wǎng)站用戶引導(dǎo)功能示例
這篇文章主要介紹了AngularJS自定義插件實(shí)現(xiàn)網(wǎng)站用戶引導(dǎo)功能,結(jié)合實(shí)例形式分析了AngularJS自定義插件的實(shí)現(xiàn)步驟與相關(guān)功能技巧,需要的朋友可以參考下2016-11-11
基于angular實(shí)現(xiàn)模擬微信小程序swiper組件
這篇文章主要介紹了基于angular實(shí)現(xiàn)模擬微信小程序swiper組件 ,需要的朋友可以參考下2017-06-06

